Loading...
Searching...
No Matches
control.h
Go to the documentation of this file.
1#ifndef _BBM_NATIVE_CONTROL_H_
2#define _BBM_NATIVE_CONTROL_H_
3
4#include <concepts>
5
7
8#include "backbone/type_traits.h"
9#include "backbone/horizontal.h"
10
11/************************************************************************/
12/*! \file control.h
13
14 \brief Data and flow control
15 + cast
16 + select
17 + lookup
18
19*************************************************************************/
20
21namespace backbone {
22
23 /*********************************************************************/
24 /*! \brief cast
25 *********************************************************************/
26 template<typename NEWTYPE, typename OLDTYPE>
27 inline constexpr NEWTYPE cast(OLDTYPE&& val)
28 {
29 return static_cast<NEWTYPE>(val);
30 }
31
32 /*********************************************************************/
33 /*! @{ \name select
34 *********************************************************************/
35 template<typename T, typename U> requires requires(std::decay_t<T> a, std::decay_t<U> b) {{a+b};}
36 inline constexpr auto select(bool mask, const T& a, const U& b)
37 {
38 using return_type = decltype( std::declval<std::decay_t<U>>() + std::declval<std::decay_t<T>>() );
39 return (mask ? return_type(a) : return_type(b));
40 }
41
42 template<typename T, typename U, size_t N> requires requires(value_t<T> a, value_t<U> b) {{a+b};}
43 inline constexpr auto select(const array<bool,N>& mask, const T& a, const U& b)
44 {
45 using return_type = decltype( std::declval<value_t<U>>() + std::declval<value_t<T>>() );
46
48 bbm::multirange_for( [](auto& r, auto& m, auto& a, auto& b) { r = select(m,a,b); }, result, mask, a, b);
49 return result;
50 }
51
52 template<typename T, typename U> requires (!is_complex_v<U>) && requires(value_t<T> a, value_t<U> b) {{a+b};}
53 inline constexpr auto select(const array<bool,2>& mask, const complex<T>& z, const U& u)
54 {
55 return select(mask, z, complex(u));
56 }
57
58 template<typename T, typename U> requires (!is_complex_v<U>) && requires(value_t<T> a, value_t<U> b) {{a+b};}
59 inline constexpr auto select(const array<bool,2>& mask, const U& u, const complex<T>& z)
60 {
61 return select(mask, complex(u), z);
62 }
63 //! @}
64
65 /**********************************************************************/
66 /*! \brief lookup
67 **********************************************************************/
68 template<typename RET, typename C> requires std::ranges::range<C> && std::convertible_to<bbm::iterable_value_t<C>, RET>
69 inline constexpr RET lookup(C&& container, size_t idx, bool mask=true)
70 {
71 // quick bail out
72 if(!mask) return RET();
73
74 // lookup
75 if(idx >= bbm::size(container)) throw bbm_out_of_range;
76 return RET(*(std::next(bbm::begin(container), idx)));
77 }
78
79 /**********************************************************************/
80 /*! \brief set
81 **********************************************************************/
82 template<typename VAL, typename C> requires std::ranges::range<C> && std::convertible_to<VAL, bbm::iterable_value_t<C>>
83 inline constexpr void set(C&& container, size_t idx, VAL&& value, bool mask=true)
84 {
85 // quick bail out
86 if(!mask) return;
87
88 // set
89 if(idx >= bbm::size(container)) throw bbm_out_of_range;
90 *(std::next(bbm::begin(container), idx)) = std::forward<VAL>(value);
91 }
92
93 /**********************************************************************/
94 /*! \brief binary_search
95 **********************************************************************/
96 template<typename C, typename PRED> requires std::ranges::range<C> && std::is_invocable_r_v<bool, PRED, bbm::iterable_value_t<C>>
97 inline constexpr size_t binary_search(C&& container, PRED&& predicate, bool mask=true)
98 {
99 using value_type = bbm::iterable_value_t<C>;
100
101 // quick exit
102 if(!mask) return bbm::size(container);
103
104 // create a wrapper for the predicate to meet stl's expectations
105 auto pred_wrapper = [&](const value_type& val, const value_type& )
106 {
107 return predicate(val);
108 };
109
110 // pass control to stl
111 return std::distance( bbm::begin(container), std::lower_bound(bbm::begin(container), bbm::end(container), value_type(), pred_wrapper) );
112 }
113
114} // end backbone namespace
115
116#endif /* _BBM_NATIVE_CONTROL_H_ */
#define bbm_out_of_range
Definition: error.h:44
ranged for loop over multiple containers at once
Random number generator; built on top of Drjit.
Definition: backbone.h:53
constexpr void set(C &&container, const Index &idx, VAL &&value, const index_mask_t< Index > &mask=true)
Non-packet set.
Definition: control.h:77
typename backbone::detail::value< std::decay_t< T > >::type value_t
Value trait.
Definition: type_traits.h:35
constexpr RET lookup(C &&container, const Index &idx, const index_mask_t< Index > &mask=true)
Non-packet look up.
Definition: control.h:61
NEWTYPE cast(OLDTYPE &&val)
cast
Definition: control.h:27
constexpr index_t< bbm::iterable_value_t< C > > binary_search(C &&container, PRED &&predicate, const index_mask_t< bbm::iterable_value_t< C > > &mask=true)
binary search
Definition: control.h:92
auto select(MASK &&mask, A &&a, B &&b)
Extension of drjit::select to diff/non-diff masks.
Definition: control.h:47
Definition: array.h:21
void multirange_for(FUNC &&func, Ts &&... containers)
ranged for loop over multiple containers at once
Definition: multirange_for.h:43
auto end(T &&t)
Definition: iterator_util.h:43
size_t size(T &&t)
Definition: iterator_util.h:22
std::decay_t< decltype(*bbm::begin(std::declval< T >()))> iterable_value_t
Definition: iterator_util.h:61
auto begin(T &&t)
Definition: iterator_util.h:29
Complex numbers.
Definition: complex.h:22