1#ifndef _BBM_BACKBONE_H_
2#define _BBM_BACKBONE_H_
21#ifndef BBM_BACKBONE_IMPORT
22 #define BBM_BACKBONE_IMPORT(Config)
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 ); \
61 template<
typename T>
requires false std::string
toString(
const T&);
62 template<
typename T>
requires false T
fromString(
const std::string&);
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) \
107 return backbone::OpName(bbm::value(t)...); \
140 #undef BBM_CALL_BACKBONE_OP
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) \
155 return apply_all( [](auto& t, auto&... u) { return backbone::FuncName(t, u...); }, t, u...); \
200 #undef BBM_CALL_BACKBONE_FUNC
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)
219 if constexpr (is_tuple_v<A> && is_tuple_v<B>)
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>>>{});
227 else if constexpr (named_equivalence_v<A,B>)
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>>>{});
232 else if constexpr (is_named_v<A> != is_named_v<B>)
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);
240 else if constexpr (concepts::reflection::supported<A> && concepts::reflection::supported<B>)
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>>;
249 else return backbone::select(std::forward<MASK>(mask), std::forward<A>(a), std::forward<B>(b));
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)
257 return bbm::detail::select(std::forward<MASK>(mask), a, b);
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)
263 return bbm::detail::select(std::forward<MASK>(mask), std::forward<A>(a), std::forward<B>(b));
280 template<
typename RET,
typename C,
typename Index>
requires
281 std::ranges::range<C> &&
282 ((std::constructible_from<RET> &&
283 ((is_tuple_v<RET> && is_tuple_v<std::ranges::range_value_t<C>>) ||
285 (concepts::reflection::supported<RET> && concepts::reflection::supported<std::ranges::range_value_t<C>>))) ||
286 requires(C&& c, Index i, index_mask_t<Index> m) {{backbone::lookup<RET>(c,i,m)};})
287 inline RET
lookup(C&& container,
const Index& idx,
const index_mask_t<Index>& mask=
true)
289 using Value = std::ranges::range_value_t<std::decay_t<C>>;
292 if constexpr (std::constructible_from<RET> && is_tuple_v<RET> && is_tuple_v<Value>)
294 static_assert(std::tuple_size_v<std::decay_t<RET>> == std::tuple_size_v<std::decay_t<Value>>,
BBM_SIZE_MISMATCH);
297 auto lookup_helper = [&]<
size_t... IDX>(std::index_sequence<IDX...>)
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 )), ...);
302 lookup_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<RET>>>{});
307 else if constexpr (std::constructible_from<RET> && named_equivalence_v<RET, Value>)
310 auto lookup_helper = [&]<
size_t... IDX>(std::index_sequence<IDX...>)
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)), ... );
315 lookup_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<RET>>>{});
322 static_assert(reflection::attributes_size<RET> == reflection::attributes_size<std::ranges::range_value_t<C>>,
BBM_SIZE_MISMATCH);
325 auto lookup_helper = [&]<
size_t... IDX>(std::index_sequence<IDX...>)
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 )), ...);
330 lookup_helper(std::make_index_sequence<reflection::attributes_size<RET>>{});
335 else return backbone::lookup<RET>(std::forward<C>(container), idx, mask);
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)
354 using CValue = std::ranges::range_value_t<C>;
357 if constexpr (is_tuple_v<Value> && is_tuple_v<CValue>)
359 static_assert(std::tuple_size_v<std::decay_t<Value>> == std::tuple_size_v<std::decay_t<CValue>>,
BBM_SIZE_MISMATCH);
361 auto set_helper = [&]<
size_t... IDX>(std::index_sequence<IDX...>)
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 ), ...);
366 set_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<CValue>>>{});
370 if constexpr (named_equivalence_v<Value, CValue>)
372 auto set_helper = [&]<
size_t... IDX>(std::index_sequence<IDX...>)
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 ), ...);
377 set_helper(std::make_index_sequence<std::tuple_size_v<std::decay_t<CValue>>>{});
383 auto set_helper = [&]<
size_t... IDX>(std::index_sequence<IDX...>)
388 set_helper(std::make_index_sequence<reflection::attributes_size<CValue>>{});
393 else backbone::set(std::forward<C>(container), idx, std::forward<Value>(
value), mask);
489 template<
typename T>
requires requires(
const T& t)
492 { backbone::fromString<T>(std::declval<std::string>()) } -> std::same_as<T>;
503 return backbone::fromString<T>(str);
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.
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.