Loading...
Searching...
No Matches
control.h
Go to the documentation of this file.
1#ifndef _BBM_CONTROL_BACKBONE_CONCEPT_H_
2#define _BBM_CONTROL_BACKBONE_CONCEPT_H_
3
4#include <vector>
5#include "concepts/util.h"
6
7/************************************************************************/
8/*! \file control.h
9
10 \brief Flow control, lookup and cast operations.
11
12*************************************************************************/
13
14namespace bbm {
15 namespace concepts {
16 namespace backbone {
17
18 /************************************************************************/
19 /*! \brief A type T has valid control methods if:
20
21 + mask_t<T> is defined
22 + value_t<T> is defined
23 + remove_diff_t<T> is defined
24 + index_t<T> is defined
25 + cast<NewType>(oldType) cast oldType to newType
26 + select(Mask, T, T) returns a type T based on the mask.
27 + lookup<T>(container, index_t, index_mask_t) returns a type T; testing on std::vector as container
28 + set(container, index_t, T, index_mask_t) set a value in a container taking; similar to lookup handles packet data
29 + binary_search(container, predicate, index_mask_t) returns the index of the first element in container for which predicate is false.
30
31*************************************************************************/
32 template<typename T>
33 concept control = requires(T a)
34 {
40
41 /****************************************************************/
42 /*! \brief cast<NEWTYPE>(T) between a type T and NEWTYPE; test with NEWTYPE == T
43 ***************************************************************/
44 { cast<T>( std::declval<T>() ) } -> std::same_as<T>;
45
46 /****************************************************************/
47 /*! \brief select(mask_t<T>, T, T) between two options based on a mask
48
49 Given a mask (possible a packet), return the first element if
50 the mask is true, otherwise return the second value. If the mask and
51 the options are packets, return a packet where each element matches
52 the choice determined by the corresponding mask
53 *****************************************************************/
54 { select( std::declval<mask_t<T>>(), a, a ) } -> std::convertible_to<T>;
55
56
57 /****************************************************************/
58 /*! \brief lookup<RET>(container, idx, mask=true)
59
60 \tparam RET = return type
61 \param container = iterable container
62 \param idx = index to gather from container either index_t<T> or size_t
63 \param mask = enable/disbale; must be index_mask_t<decltype(idx)>
64
65 Must support the following four cases:
66
67 Case 0: RET!=packet, Value(C)!=packet, Index!=packet
68 Case 1: RET==packet, Value(C)==packet, Index!=packet
69 Case 2: RET==packet, Value(C)!=packet, Index==packet
70 Case 3: RET==packet, Value(C)==packet, Index==packet
71
72 Case 0 and 1 are equal to a regular lookup: container[idx] & mask.
73 Case 2 is equivallent to: RET[i] = C[idx[i]] & mask[i]
74 Case 3 is equivallent to: RET[i] = C[idx[i]][i] & mask[i]
75
76 Thus either: (Value(C) == packet) == (RET == Packet) or (RET ==
77 Packet) == (Index == Packet).
78
79 Check concept for std::vector as container and all combinations for
80 which RET = T
81 *****************************************************************/
82 { lookup<T>( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<size_t>(), std::declval<index_mask_t<size_t>>() ) } -> std::convertible_to<T>; // Case 0
83 { lookup<T>( std::declval<std::vector<T>>(), std::declval<size_t>(), std::declval<index_mask_t<size_t>>() ) } -> std::convertible_to<T>; // Case 1
84 { lookup<T>( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<index_t<T>>(), std::declval<index_mask_t<T>>() ) } -> std::convertible_to<T>; // Case 2
85 { lookup<T>( std::declval<std::vector<T>>(), std::declval<index_t<T>>(), std::declval<index_mask_t<T>>() ) } -> std::convertible_to<T>; // Case 3
86
87 { lookup<T>( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<size_t>() ) } -> std::convertible_to<T>; // Case 0; default mask
88 { lookup<T>( std::declval<std::vector<T>>(), std::declval<size_t>()) } -> std::convertible_to<T>; // Case 1; default mask
89 { lookup<T>( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<index_t<T>>() ) } -> std::convertible_to<T>; // Case 2; default mask
90 { lookup<T>( std::declval<std::vector<T>>(), std::declval<index_t<T>>() ) } -> std::convertible_to<T>; // Case 3; default mask
91
92 /****************************************************************/
93 /*! \brief set(container, idx, value, mask=true)
94
95 \param container = iterable container
96 \param idx = index to set; either index_t<T> or size_t
97 \param value = value to set
98 \param mask = enable/disable; must be index_mask_t<decltype(idx)>
99
100 Must supprt the following four cases:
101
102 Case 0: VAL!=packet, Value(C)!=packet, Index!=packet
103 Case 1: VAL==packet, Value(C)==packet, Index!=packet
104 Case 2: VAL==packet, Value(C)!=packet, Index==packet
105 Case 3: VAL==packet, Value(C)==packet, Index==packet
106
107 Case 0 and 1 are equivalent to container[idx] = value
108 Case 2 is equivallent to if(mask[i]) C[idx[i]] = value[i]
109 Case 3 is equivallent to if(mask[i]) C[idx[i]][i] = value[i]
110
111 Check concept for std::vector as container for all combinations with VAL=T
112 *****************************************************************/
113 { set( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<size_t>(), std::declval<remove_packet_t<T>>(), std::declval<index_mask_t<size_t>>() ) }; // Case 0
114 { set( std::declval<std::vector<T>>(), std::declval<size_t>(), std::declval<T>(), std::declval<index_mask_t<size_t>>() ) }; // Case 1
115 { set( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<index_t<T>>(), std::declval<T>(), std::declval<index_mask_t<T>>() ) }; // Case 2
116 { set( std::declval<std::vector<T>>(), std::declval<index_t<T>>(), std::declval<T>(), std::declval<index_mask_t<T>>() ) }; // Case 3
117
118 { set( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<size_t>(), std::declval<remove_packet_t<T>>() ) }; // Case 0; default mask
119 { set( std::declval<std::vector<T>>(), std::declval<size_t>(), std::declval<T>() ) }; // Case 1; default mask
120 { set( std::declval<std::vector<remove_packet_t<T>>>(), std::declval<index_t<T>>(), std::declval<T>() ) }; // Case 2; default mask
121 { set( std::declval<std::vector<T>>(), std::declval<index_t<T>>(), std::declval<T>() ) }; // Case 3; default mask
122
123 /****************************************************************/
124 /*! \brief binary_search(containr, predicate, mask=true)
125
126 \param container = iterable container of data to search
127
128 \param predicate = a function that takes a data element from the
129 contrainer and returns a mask indicating whether
130 if meets or does not meet the condition.
131 \param mask = enable/disable lanes
132 \returns the index of first element (per lane) for which the
133 predicate is false. Return container.size() if all are
134 true.
135
136 Check concept for std::vector<T> and a placeholder predicate
137 ***************************************************************/
138 { binary_search( std::declval<std::vector<T>>(), [](const T&) { return true; }, std::declval<index_mask_t<T>>() ) } -> std::convertible_to< index_t<T> >;
139 { binary_search( std::declval<std::vector<T>>(), [](const T&) { return true; } ) } -> std::convertible_to< index_t<T> >;
140
141 };
142
143
144 } // end backbone namespace
145 } // end concepts namespace
146} // end bbm namespace
147
148#endif /* _BBM_CONTROL_BACKBONE_CONCEPT_H_ */
149
A type T has valid control methods if:
Definition: control.h:33
Definition: util.h:25
Random number generator; built on top of Drjit.
Definition: backbone.h:53
Definition: aggregatebsdf.h:29
constexpr auto select(MASK &&mask, const A &a, const A &b)
Definition: backbone.h:255
void set(C &&container, const Index &idx, Value &&value, const index_mask_t< Index > &mask=true)
Generalization of backbone::set to include tuples/named/reflection-supported objects.
Definition: backbone.h:352
Additional basic helper concepts.