Loading...
Searching...
No Matches
backbone.h
Go to the documentation of this file.
1#ifndef _BBM_BACKBONE_H_
2#define _BBM_BACKBONE_H_
3
4#include "concepts/util.h"
5
6#include "util/tuple.h"
7#include "util/named.h"
8#include "util/reflection.h"
9#include "util/apply_all.h"
10
11/************************************************************************/
12/*! \file backbone.h
13
14 \brief Active the current backbone.
15
16************************************************************************/
17
18/************************************************************************/
19/*! \brief BBM_BACKBONE_IMPORT: will be called each time BBM_IMPORT_CONFIG is called; default do nothing
20*************************************************************************/
21#ifndef BBM_BACKBONE_IMPORT
22 #define BBM_BACKBONE_IMPORT(Config)
23#endif
24
25/************************************************************************/
26/*! \brief Helper Macro to validate the backbone for a given type
27 + TYPE has basic_math (+, -, *, /, %)
28 + TYPE supports (==, !=, <, >, <=, and >=)
29 + TYPE supports horizontal operations
30 + TYPE supports the control method select, lookup, and detach.
31 + mask_t<TYPE> is valid (bit and logical operators)
32 + replace_scalar_t<TYPE> is a valid size_t.
33*************************************************************************/
34#define BBM_VALIDATE_BACKBONE(TYPE) \
35 BBM_CHECK_RAW_CONCEPT( std::constructible_from, TYPE ); \
36 BBM_CHECK_RAW_CONCEPT( std::copy_constructible, TYPE ); \
37 BBM_CHECK_RAW_CONCEPT( bbm::concepts::has_basic_math, TYPE ); \
38 BBM_CHECK_RAW_CONCEPT( bbm::concepts::backbone::has_math_functions, TYPE ); \
39 BBM_CHECK_RAW_CONCEPT( bbm::concepts::backbone::ordered, TYPE ); \
40 BBM_CHECK_RAW_CONCEPT( bbm::concepts::backbone::horizontal, TYPE ); \
41 BBM_CHECK_RAW_CONCEPT( bbm::concepts::backbone::control, TYPE ); \
42 BBM_CHECK_RAW_CONCEPT( bbm::concepts::backbone::is_rng, bbm::rng<TYPE> ); \
43 BBM_CHECK_RAW_CONCEPT( bbm::concepts::has_logical_operators, bbm::mask_t<TYPE> ); \
44 BBM_CHECK_RAW_CONCEPT( bbm::concepts::has_bit_operators, bbm::mask_t<TYPE> ); \
45 BBM_CHECK_RAW_CONCEPT( bbm::concepts::has_basic_math, bbm::replace_scalar_t<TYPE, size_t>); \
46 BBM_CHECK_RAW_CONCEPT( bbm::concepts::has_increment, bbm::replace_scalar_t<TYPE, size_t> ); \
47 BBM_CHECK_RAW_CONCEPT( bbm::concepts::has_decrement, bbm::replace_scalar_t<TYPE, size_t> ); \
48 BBM_CHECK_RAW_CONCEPT( bbm::concepts::backbone::if_diff_gradient, TYPE ); \
49 BBM_CHECK_RAW_CONCEPT( bbm::concepts::stringconvert, TYPE ); \
50
51
52/*** Forward Declarations for backbone ***/
53namespace backbone {
54 template<typename T> remove_diff_t<T>& detach_gradient(T&);
55 template<typename T> void track_gradient(T&, bool);
56 template<typename T> bool is_gradient_tracked(T&);
57 template<typename T> const remove_diff_t<T>& gradient(T&);
58 template<typename T> void forward_gradient(T&);
59 template<typename T> void backward_gradient(T&);
60
61 template<typename T> requires false std::string toString(const T&);
62 template<typename T> requires false T fromString(const std::string&);
63}
64
65//////////////////////////////////////////////////////////////////////////
66namespace bbm {
67
68 //! @{ \name type_traits
73
78 using backbone::mask_t;
84 //! @}
85
86 //! @{ \name import core types
87 using backbone::vec2d;
88 using backbone::vec3d;
89 using backbone::color;
91 //! @}
92
93 //! @{ \name random number generator
94 using backbone::seed_t;
96 using backbone::rng;
97 //! @}
98
99
100 /**********************************************************************/
101 /*! \brief Helper macro: extend existing methods to support attribute types
102 **********************************************************************/
103#define BBM_CALL_BACKBONE_OP(OpName) \
104 template<typename... T> requires requires(const T&... t) {{backbone::OpName(bbm::value(t)...)};} \
105 inline constexpr auto OpName(const T&... t) \
106 { \
107 return backbone::OpName(bbm::value(t)...); \
108 } \
109
110 //! @{ \name math functions
117 //! @}
118
119 //! @{ \name complex functions
123 //! @}
124
125 //! @{ \name horizontal methods
132 BBM_CALL_BACKBONE_OP(squared_norm);
138 //! @}
139
140 #undef BBM_CALL_BACKBONE_OP
141
142 //! @{ \name control methods
143 using backbone::cast;
145
146
147 /**********************************************************************/
148 /* \brief Helper Macro for extending backbone methods to support tuples
149 named, and unnamed accessible types.
150 **********************************************************************/
151#define BBM_CALL_BACKBONE_FUNC(FuncName) \
152 template<typename T, typename... U> requires requires(const T& t, const U&... u) {{apply_all([](auto& t, auto&... u) { return backbone::FuncName(t, u...); }, t, u...)};} \
153 inline auto FuncName (const T& t, const U&... u) \
154 { \
155 return apply_all( [](auto& t, auto&... u) { return backbone::FuncName(t, u...); }, t, u...); \
156 } \
157
158 //! @{ Math functions (only those that return the same type are extended to tupe/named/unnamed)
179 BBM_CALL_BACKBONE_FUNC( copysign )
188 BBM_CALL_BACKBONE_FUNC( safe_sqrt )
189 BBM_CALL_BACKBONE_FUNC( safe_asin )
190 BBM_CALL_BACKBONE_FUNC( safe_acos )
193 BBM_CALL_BACKBONE_FUNC( erfinv )
194 BBM_CALL_BACKBONE_FUNC( tgamma )
195 BBM_CALL_BACKBONE_FUNC( lgamma )
198 //! @}
199
200 #undef BBM_CALL_BACKBONE_FUNC
201
202
203 namespace detail {
204 /********************************************************************/
205 /*! \brief Generalized 'select' A or B based on the MASK.
206
207 \param mask = selection mask; true => select A; otherwise B.
208 \param a = select if true
209 \param b = select if false
210
211 If A and B are tuples, named tuples, or support reflection, then
212 perform selection on all elements based on binary mask (i.e., all
213 elements of A are copied, or all elements of B are selected).
214 *********************************************************************/
215 template<typename MASK, typename A, typename B> requires (concepts::reflection::supported<A> && concepts::reflection::supported<B>) || (is_tuple_v<anonymize_t<A>> && is_tuple_v<anonymize_t<B>>) || requires(MASK m, A a, B b) {{backbone::select(m,a,b)};}
216 inline constexpr auto select(MASK&& mask, A&& a, B&& b)
217 {
218 // Case 1: tuples
219 if constexpr (is_tuple_v<A> && is_tuple_v<B>)
220 {
221 static_assert(std::tuple_size_v<std::decay_t<A>> == std::tuple_size_v<std::decay_t<B>>, BBM_SIZE_MISMATCH);
222 auto select_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>) { return make_ref_tuple( bbm::detail::select(std::forward<MASK>(mask), std::get<IDX>(std::forward<A>(a)), std::get<IDX>(std::forward<B>(b)))... ); };
223 return select_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<A>>>{});
224 }
225
226 // Case 2: named tuples
227 else if constexpr (named_equivalence_v<A,B>)
228 {
229 auto select_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>) { return make_named< std::decay_t<A>::template name<IDX>... >( make_ref_tuple( bbm::detail::select(std::forward<MASK>(mask), bbm::get<std::decay_t<A>::template name<IDX>>(a), bbm::get<std::decay_t<A>::template name<IDX>>(b))... ) ); };
230 return select_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<A>>>{});
231 }
232 else if constexpr (is_named_v<A> != is_named_v<B>)
233 {
234 auto select_helper = [&]<typename T, string_literal... NAMES>(named<T,NAMES...>) { return make_named<NAMES...>( bbm::detail::select(mask, anonymize_v(a), anonymize_v(b) ) ); };
235 if constexpr (is_named_v<A>) return select_helper(a);
236 else if constexpr (is_named_v<B>) return select_helper(b);
237 }
238
239 // Case 3: supports refllection
240 else if constexpr (concepts::reflection::supported<A> && concepts::reflection::supported<B>)
241 {
242 using result_t = std::conditional_t<std::is_convertible_v<std::decay_t<A>, std::decay_t<B>>, std::decay_t<B>, std::decay_t<A>>;
243 result_t result;
244 reflection::attributes(result) = bbm::detail::select(std::forward<MASK>(mask), reflection::attributes(std::forward<A>(a)), reflection::attributes(std::forward<B>(b)));
245 return result;
246 }
247
248 // Otherwise forward to backbone
249 else return backbone::select(std::forward<MASK>(mask), std::forward<A>(a), std::forward<B>(b));
250 }
251 } // end detail namespace
252
253 //! @{ \name select generalization to (named) tuples and types with reflection support
254 template<typename MASK, typename A> requires (concepts::reflection::supported<A> || is_tuple_v<anonymize_t<A>>)
255 inline constexpr auto select(MASK&& mask, const A& a, const A& b) // Allow for passing initializer list as first or second argument for types with reflection or tuples (others should be handled by backbone::select)
256 {
257 return bbm::detail::select(std::forward<MASK>(mask), a, b);
258 }
259
260 template<typename MASK, typename A, typename B> requires requires(MASK m, A a, B b) {{bbm::detail::select(m,a,b)};}
261 inline constexpr auto select(MASK&& mask, A&& a, B&& b) // General case; heterogeneous arguments
262 {
263 return bbm::detail::select(std::forward<MASK>(mask), std::forward<A>(a), std::forward<B>(b));
264 }
265 //! @}
266
267 /**********************************************************************/
268 /*! \brief Generalize backbone::lookup to include containers of tuples/named
269 tuples/reflection-supported types
270
271 \tparam RET = return type; must support reflection
272 \param container = a container to lookup from
273 \param idx = index of the elements to lookup
274 \param mask = enable/disable lanes
275
276 When tuple/named or reflection supported type, we lookup each element
277 seperately to support packet data structures.
278
279 **********************************************************************/
280 template<typename RET, typename C, typename Index> requires
281 std::ranges::range<C> && // C must be a range
282 ((std::constructible_from<RET> && // (trivially constructible AND
283 ((is_tuple_v<RET> && is_tuple_v<std::ranges::range_value_t<C>>) || // (tuple OR
284 (named_equivalence_v<RET, std::ranges::range_value_t<C>>) || // named OR
285 (concepts::reflection::supported<RET> && concepts::reflection::supported<std::ranges::range_value_t<C>>))) || // unnamed)) OR
286 requires(C&& c, Index i, index_mask_t<Index> m) {{backbone::lookup<RET>(c,i,m)};}) // has backbone support
287 inline RET lookup(C&& container, const Index& idx, const index_mask_t<Index>& mask=true)
288 {
289 using Value = std::ranges::range_value_t<std::decay_t<C>>;
290
291 // Case 1: tuples
292 if constexpr (std::constructible_from<RET> && is_tuple_v<RET> && is_tuple_v<Value>)
293 {
294 static_assert(std::tuple_size_v<std::decay_t<RET>> == std::tuple_size_v<std::decay_t<Value>>, BBM_SIZE_MISMATCH);
295
296 RET result;
297 auto lookup_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>)
298 {
299 ((std::get<IDX>(result) = bbm::lookup< std::decay_t<decltype(std::get<IDX>(result))> >( std::ranges::views::transform(container, [](auto&& v) { return std::get<IDX>(std::forward<decltype(v)>(v)); }), idx, mask )), ...);
300 };
301
302 lookup_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<RET>>>{});
303 return result;
304 }
305
306 // Case 2: named
307 else if constexpr (std::constructible_from<RET> && named_equivalence_v<RET, Value>)
308 {
309 RET result;
310 auto lookup_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>)
311 {
312 ((bbm::get<std::decay_t<RET>::template name<IDX>>(result) = bbm::lookup< std::decay_t<decltype(bbm::get<std::decay_t<RET>::template name<IDX>>(result))> >( std::ranges::views::transform(container, [](auto&& v) { return bbm::get<std::decay_t<RET>::template name<IDX>>(std::forward<decltype(v)>(v)); }), idx, mask)), ... );
313 };
314
315 lookup_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<RET>>>{});
316 return result;
317 }
318
319 // Case 3: reflection support
320 else if constexpr (std::constructible_from<RET> && concepts::reflection::supported<RET> && concepts::reflection::supported<Value>)
321 {
322 static_assert(reflection::attributes_size<RET> == reflection::attributes_size<std::ranges::range_value_t<C>>, BBM_SIZE_MISMATCH);
323
324 RET result;
325 auto lookup_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>)
326 {
327 ((std::get<IDX>(reflection::attributes(result)) = bbm::lookup<std::decay_t<std::tuple_element_t<IDX,reflection::attributes_t<RET>>>>( std::ranges::views::transform(container, [](auto&& v) { return std::get<IDX>(reflection::attributes(std::forward<decltype(v)>(v))); }), idx, mask )), ...);
328 };
329
330 lookup_helper(std::make_index_sequence<reflection::attributes_size<RET>>{});
331 return result;
332 }
333
334 // Otherwise forward to backbone
335 else return backbone::lookup<RET>(std::forward<C>(container), idx, mask);
336 }
337
338 /**********************************************************************/
339 /*! \brief Generalization of backbone::set to include
340 tuples/named/reflection-supported objects.
341
342 \param container: container to set data in
343 \param indx: index at which to set the data
344 \param value: value to store
345 \param mask: enable/disbale lanes
346
347 When tuple/named or reflection-type, we set each element seperately to
348 support packet data structures.
349
350 ***********************************************************************/
351 template<typename Value, typename C, typename Index>
352 inline void set(C&& container, const Index& idx, Value&& value, const index_mask_t<Index>& mask=true)
353 {
354 using CValue = std::ranges::range_value_t<C>;
355
356 // Case 1: tuple
357 if constexpr (is_tuple_v<Value> && is_tuple_v<CValue>)
358 {
359 static_assert(std::tuple_size_v<std::decay_t<Value>> == std::tuple_size_v<std::decay_t<CValue>>, BBM_SIZE_MISMATCH);
360
361 auto set_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>)
362 {
363 (bbm::set(std::ranges::views::transform(std::forward<C>(container), [](auto&& v) -> decltype(auto) { return std::get<IDX>(std::forward<decltype(v)>(v)); }), idx, std::get<IDX>(std::forward<Value>(value)), mask ), ...);
364 };
365
366 set_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<CValue>>>{});
367 }
368
369 // Case 2: named
370 if constexpr (named_equivalence_v<Value, CValue>)
371 {
372 auto set_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>)
373 {
374 (bbm::set(std::ranges::views::transform(std::forward<C>(container), [](auto&& v) -> decltype(auto) { return bbm::get<std::decay_t<CValue>::template name<IDX>>(std::forward<decltype(v)>(v)); }), idx, bbm::get<std::decay_t<CValue>::template name<IDX>>(std::forward<Value>(value)), mask ), ...);
375 };
376
377 set_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<CValue>>>{});
378 }
379
380 // Case 3: reflection supported
382 {
383 auto set_helper = [&]<size_t... IDX>(std::index_sequence<IDX...>)
384 {
385 (bbm::set(std::ranges::views::transform(std::forward<C>(container), [](auto&& v) -> decltype(auto) { return std::get<IDX>(reflection::attributes(std::forward<decltype(v)>(v))); }), idx, std::get<IDX>(reflection::attributes(std::forward<Value>(value))), mask ), ...);
386 };
387
388 set_helper(std::make_index_sequence<reflection::attributes_size<CValue>>{});
389
390 }
391
392 // Otherwise forward to backbone
393 else backbone::set(std::forward<C>(container), idx, std::forward<Value>(value), mask);
394 }
395
396 //! @{ \name Gradient methods
397
398 /**********************************************************************/
399 /*! \brief Detach the value from the gradient computations
400
401 \param t = variable to detach
402 \returns a reference to the raw value
403
404 Note: if the variable does not support gradients, then the value is
405 returned unchanged.
406 ***********************************************************************/
407 template<typename T>
409 {
410 if constexpr (is_diff_v<T>) { return backbone::detach_gradient(t); }
411 else { return t; }
412 }
413
414 /**********************************************************************/
415 /*! \brief Return the gradient
416
417 \param t = variable to return the tracked gradient
418 \returns tracked gradient (const reference)
419
420 static_assert if T is not differentiable.
421 ***********************************************************************/
422 template<typename T>
423 auto gradient(T& t)
424 {
425 static_assert(is_diff_v<T>, BBM_NOT_DIFF);
426 return backbone::gradient(t);
427 }
428
429 /**********************************************************************/
430 /*! \brief Checks if gradients are enabled for a variable
431
432 \param t = variable to check
433 \returns true if the variable is tracked.
434 ***********************************************************************/
435 template<typename T>
436 bool is_gradient_tracked(const T& t)
437 {
438 if constexpr (is_diff_v<T>) { return backbone::is_gradient_tracked(t); }
439 else return false;
440 }
441
442 /**********************************************************************/
443 /*! \brief Enable/disable tracking of gradients for a variable
444
445 \param t = variable to track
446 \param toggle = enable/disable
447
448 static_assert if T is not differentiable.
449 ***********************************************************************/
450 template<typename T>
451 void track_gradient(T& t, bool toggle=true)
452 {
453 static_assert(is_diff_v<T>, BBM_NOT_DIFF);
454 backbone::track_gradient(t, toggle);
455 }
456
457 /**********************************************************************/
458 /*! \brief Enable forward gradient tracking
459
460 \param t = variable to track
461
462 static_assert if T is not differentiable.
463 ***********************************************************************/
464 template<typename T>
466 {
467 static_assert(is_diff_v<T>, BBM_NOT_DIFF);
469 }
470
471 /**********************************************************************/
472 /*! \brief Enable backward/reverse gradient tracking
473
474 \param t = variable to track
475
476 static_assert if T is not differentiable.
477 ***********************************************************************/
478 template<typename T>
480 {
481 static_assert(is_diff_v<T>, BBM_NOT_DIFF);
483 }
484 //! @}
485
486 /**********************************************************************/
487 /*! \brief string convert of backbone types
488 *********************************************************************/
489 template<typename T> requires requires(const T& t)
490 {
491 { backbone::toString(t) } -> std::convertible_to<std::string>;
492 { backbone::fromString<T>(std::declval<std::string>()) } -> std::same_as<T>;
493 }
495 {
496 static inline std::string toString(const T& t)
497 {
498 return backbone::toString(t);
499 }
500
501 static inline T fromString(const std::string& str)
502 {
503 return backbone::fromString<T>(str);
504 }
505 };
506
507} // end bbm namespace
508
509
510/************************************************************************/
511/* Include backbone concepts after the declaration of the bbm namespace
512 since the concepts assume the methods and typedefs are declared
513*************************************************************************/
514#include "concepts/macro.h"
524
525#endif /* _BBM_BACKBONE_H_ */
concept to check if a class supports reflections
Definition: reflection.h:58
#define BBM_NOT_DIFF
Definition: error.h:52
#define BBM_SIZE_MISMATCH
Definition: error.h:50
Additional requirements for the complex data-type (in addition to all other backbone type requirement...
Flow control, lookup and cast operations.
A differentiable type T has valid gradient operations if:
Horizontal operators (aggregation over all elements in the type)
Extended math functionality.
Random number generator.
Each core type of the backbone must have appropriate methods for converting the core type to and from...
A valid backbone type must have the following type_traits:
#define BBM_CALL_BACKBONE_OP(OpName)
Helper macro: extend existing methods to support attribute types.
Definition: backbone.h:103
#define BBM_CALL_BACKBONE_FUNC(FuncName)
Definition: backbone.h:151
Macros for checking if a class meets a concept.
Random number generator; built on top of Drjit.
Definition: backbone.h:53
bool is_gradient_tracked(T &)
drjit::Array< T, 3 > color
Definition: color.h:13
typename detail::remove_packet< std::decay_t< T > >::type remove_packet_t
Strip packet type from T.
Definition: type_traits.h:154
void forward_gradient(T &)
drjit::Array< T, 3 > vec3d
Definition: vec.h:16
constexpr bool is_packet_v
true is the type is a packet
Definition: type_traits.h:133
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 detail::index_impl< std::decay_t< T > >::mask index_mask_t
Return the mask of an index of a type.
Definition: type_traits.h:215
constexpr bool is_diff_v
true if type supports autodiff
Definition: type_traits.h:68
constexpr bool is_index_v
true if the type is an index type
Definition: type_traits.h:209
const remove_diff_t< T > & gradient(T &)
drjit::scalar_t< std::decay_t< T > > scalar_t
Scalar trait.
Definition: type_traits.h:36
typename backbone::detail::value< std::decay_t< T > >::type value_t
Value trait.
Definition: type_traits.h:35
drjit::mask_t< T > mask_t
Direct mapping to DrJIT traits.
Definition: type_traits.h:32
remove_diff_t< T > & detach_gradient(T &)
void backward_gradient(T &)
NEWTYPE cast(OLDTYPE &&val)
cast
Definition: control.h:27
void track_gradient(T &, bool)
typename detail::index_impl< std::decay_t< T > >::type index_t
Return the index type.
Definition: type_traits.h:203
uint64_t seed_t
seed type
Definition: random.h:22
drjit::Array< T, 2 > vec2d
Definition: vec.h:13
constexpr bool is_mask_v
Definition: type_traits.h:33
std::string toString(const T &)
regular drjit::array types
Definition: stringconvert.h:21
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
static constexpr seed_t default_seed
Definition: random.h:27
auto select(MASK &&mask, A &&a, B &&b)
Extension of drjit::select to diff/non-diff masks.
Definition: control.h:47
drjit::replace_scalar_t< std::decay_t< T >, R > replace_scalar_t
Replace_scalar trait.
Definition: type_traits.h:37
T fromString(const std::string &)
Definition: stringconvert.h:31
typename detail::remove_diff< std::decay_t< T > >::type remove_diff_t
Strip autodiff from type T.
Definition: type_traits.h:95
Definition: type_traits.h:63
Definition: type_traits.h:74
constexpr decltype(auto) attributes(T &&t)
Definition: reflection.h:200
Definition: aggregatebsdf.h:29
constexpr named< anonymize_t< T >, NAMES... > make_named(T &&t)
Make a named of a gettable type (with size == #NAMES); renames if the type is a named container.
Definition: named.h:293
void track_gradient(T &t, bool toggle=true)
Enable/disable tracking of gradients for a variable.
Definition: backbone.h:451
constexpr auto select(MASK &&mask, const A &a, const A &b)
Definition: backbone.h:255
constexpr auto make_ref_tuple(ARGS &&... args)
Make a tuple of references.
Definition: tuple.h:46
static constexpr bool named_equivalence_v
Definition: named.h:285
constexpr decltype(auto) anonymize_v(T &&t)
Definition: named.h:261
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
void backward_gradient(T &t)
Enable backward/reverse gradient tracking.
Definition: backbone.h:479
constexpr bool is_tuple_v
Definition: type_traits.h:145
bool is_gradient_tracked(const T &t)
Checks if gradients are enabled for a variable.
Definition: backbone.h:436
constexpr decltype(auto) get(T &&src)
Definition: named.h:317
auto gradient(T &t)
Return the gradient.
Definition: backbone.h:423
RET lookup(C &&container, const Index &idx, const index_mask_t< Index > &mask=true)
Generalize backbone::lookup to include containers of tuples/named tuples/reflection-supported types.
Definition: backbone.h:287
decltype(auto) value(T &&t)
return the value of an attribute, or if not an attribute the object
Definition: attribute_value.h:20
void forward_gradient(T &t)
Enable forward gradient tracking.
Definition: backbone.h:465
auto detach_gradient(T &t)
Detach the value from the gradient computations.
Definition: backbone.h:408
A valid ordering requires that the type has eq, neq, <, >, <=, and => operators that each return the ...
Complex numbers.
Definition: complex.h:22
Random generator wrapper around Drjit's PCG32.
Definition: random.h:34
static std::string toString(const T &t)
Definition: backbone.h:496
static T fromString(const std::string &str)
Definition: backbone.h:501
forward decalaration
Definition: stringconvert.h:47
Extensions for the STL tuple class.
A wrapper for STL containers such as tuple, pair, and array. These containers force the programmer to...
Compile-time reflection of:
Additional basic helper concepts.