3 #include <funcy/concepts.h> 4 #include <funcy/util/chainer.h> 5 #include <funcy/util/compute_product.h> 6 #include <funcy/util/compute_sum.h> 7 #include <funcy/util/derivative_wrappers.h> 8 #include <funcy/util/evaluate_if_present.h> 9 #include <funcy/util/type_traits.h> 11 #include <type_traits> 20 template < Function F, Function G >
21 struct Product : Chainer< Product< F, G > >
24 template <
class IndexedArg >
25 using D1Type = ComputeSum< ComputeProduct< D1< F, IndexedArg >, D0< G > >,
26 ComputeProduct< D0< F >, D1< G, IndexedArg > > >;
28 template <
class IndexedArgX,
class IndexedArgY >
29 using D2Type = ComputeSum< ComputeProduct< D2< F, IndexedArgX, IndexedArgY >, D0< G > >,
30 ComputeProduct< D1< F, IndexedArgX >, D1< G, IndexedArgY > >,
31 ComputeProduct< D1< F, IndexedArgY >, D1< G, IndexedArgX > >,
32 ComputeProduct< D0< F >, D2< G, IndexedArgX, IndexedArgY > > >;
34 template <
class IndexedArgX,
class IndexedArgY,
class IndexedArgZ >
36 ComputeSum< ComputeProduct< D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >, D0< G > >,
37 ComputeProduct< D2< F, IndexedArgX, IndexedArgY >, D1< G, IndexedArgZ > >,
38 ComputeProduct< D2< F, IndexedArgX, IndexedArgZ >, D1< G, IndexedArgY > >,
39 ComputeProduct< D1< F, IndexedArgX >, D2< G, IndexedArgY, IndexedArgZ > >,
40 ComputeProduct< D2< F, IndexedArgY, IndexedArgZ >, D1< G, IndexedArgX > >,
41 ComputeProduct< D1< F, IndexedArgY >, D2< G, IndexedArgX, IndexedArgZ > >,
42 ComputeProduct< D1< F, IndexedArgZ >, D2< G, IndexedArgX, IndexedArgY > >,
43 ComputeProduct< D0< F >, D3< G, IndexedArgX, IndexedArgY, IndexedArgZ > > >;
51 constexpr
Product(
const F& f_,
const G& g_ )
52 : f( f_ ), g( g_ ), value( multiply_via_traits( f(), g() ) )
62 : f( f_ ), g( std::move( g_ ) ), value( multiply_via_traits( f(), g() ) )
72 : f( std::move( f_ ) ), g( g_ ), value( multiply_via_traits( f(), g() ) )
82 : f( std::move( f_ ) ), g( std::move( g_ ) ), value( multiply_via_traits( f(), g() ) )
91 template <
class InitF,
class InitG >
92 constexpr
Product( InitF&& f_, InitG&& g_ ) requires(
93 std::is_constructible_v< F, std::decay_t< InitF > >&&
94 std::is_constructible_v< G, std::decay_t< InitG > > )
95 : f( std::forward< InitF >( f_ ) ), g( std::forward< InitG >( g_ ) ),
96 value( multiply_via_traits( f(), g() ) )
101 template <
class Arg >
104 update_if_present( f, x );
105 update_if_present( g, x );
106 value = multiply_via_traits( f(), g() );
110 template <
int index,
class Arg >
113 update_if_present< index >( f, x );
114 update_if_present< index >( g, x );
115 value = multiply_via_traits( f(), g() );
118 template <
class... IndexedArgs >
119 void bulk_update( IndexedArgs&&... args )
121 bulk_update_if_present( f, args... );
122 bulk_update_if_present( g, std::forward< IndexedArgs >( args )... );
123 value = multiply_via_traits( f(), g() );
127 constexpr decltype(
auto ) d0()
const noexcept
136 template <
int id,
class Arg,
class IndexedArg = IndexedType< Arg,
id > >
137 auto d1( Arg
const& dx )
const requires( D1Type< IndexedArg >::present )
139 return sum( product( D1< F, IndexedArg >( f, dx ), D0< G >( g ) ),
140 product( D0< F >( f ), D1< G, IndexedArg >( g, dx ) ) )();
148 template <
int idx,
int idy,
class ArgX,
class ArgY,
151 auto d2( ArgX
const& dx, ArgY
const& dy )
const 152 requires( D2Type< IndexedArgX, IndexedArgY >::present )
154 return sum( product( D2< F, IndexedArgX, IndexedArgY >( f, dx, dy ), D0< G >( g ) ),
155 product( D1< F, IndexedArgX >( f, dx ), D1< G, IndexedArgY >( g, dy ) ),
156 product( D1< F, IndexedArgY >( f, dy ), D1< G, IndexedArgX >( g, dx ) ),
157 product( D0< F >( f ), D2< G, IndexedArgX, IndexedArgY >( g, dx, dy ) ) )();
166 template <
int idx,
int idy,
int idz,
class ArgX,
class ArgY,
class ArgZ,
170 auto d3( ArgX
const& dx, ArgY
const& dy, ArgZ
const& dz )
const 171 requires( D3Type< IndexedArgX, IndexedArgY, IndexedArgZ >::present )
173 return sum( product( D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >( f, dx, dy, dz ),
175 product( D2< F, IndexedArgX, IndexedArgY >( f, dx, dy ),
176 D1< G, IndexedArgZ >( g, dz ) ),
177 product( D2< F, IndexedArgX, IndexedArgZ >( f, dx, dz ),
178 D1< G, IndexedArgY >( g, dy ) ),
179 product( D1< F, IndexedArgX >( f, dx ),
180 D2< G, IndexedArgY, IndexedArgZ >( g, dy, dz ) ),
181 product( D2< F, IndexedArgY, IndexedArgZ >( f, dy, dz ),
182 D1< G, IndexedArgX >( g, dx ) ),
183 product( D1< F, IndexedArgY >( f, dy ),
184 D2< G, IndexedArgX, IndexedArgZ >( g, dx, dz ) ),
185 product( D1< F, IndexedArgZ >( f, dz ),
186 D2< G, IndexedArgX, IndexedArgY >( g, dx, dy ) ),
187 product( D0< F >( f ), D3< G, IndexedArgX, IndexedArgY, IndexedArgZ >(
188 g, dx, dy, dz ) ) )();
void update(Arg const &x)
Update point of evaluation.
Definition: product.h:102
auto d2(ArgX const &dx, ArgY const &dy) const requires(D2Type< IndexedArgX
Second directional derivative.
constexpr Product(const F &f_, const G &g_)
Constructor passing arguments to function constructors.
Definition: product.h:51
constexpr Product(F &&f_, G &&g_)
Constructor passing arguments to function constructors.
Definition: product.h:81
constexpr Product(const F &f_, G &&g_)
Constructor passing arguments to function constructors.
Definition: product.h:61
auto d3(ArgX const &dx, ArgY const &dy, ArgZ const &dz) const requires(D3Type< IndexedArgX
Third directional derivative.
Mathematical operations and corresponding differentation rules.
constexpr Product(F &&f_, const G &g_)
Constructor passing arguments to function constructors.
Definition: product.h:71
Product of functions of type F and G.
Definition: product.h:21
auto d1(Arg const &dx) const requires(D1Type< IndexedArg >
First directional derivative.
Definition: product.h:137
typename Decay< std::decay_t< F > >::type decay_t
Access underlying type (if it is hidden by expression templates).
Definition: type_traits.h:47
constexpr Product(InitF &&f_, InitG &&g_) requires(std
Constructor passing arguments to function constructors.
Definition: product.h:92
Definition: type_traits.h:54
void update(const Arg &x)
Update variable corresponding to index.
Definition: product.h:111