funcy  1.6.1
product.h
1 #pragma once
2 
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>
10 
11 #include <type_traits>
12 #include <utility>
13 
14 namespace funcy::mathop
15 {
20  template < Function F, Function G >
21  struct Product : Chainer< Product< F, G > >
22  {
23  private:
24  template < class IndexedArg >
25  using D1Type = ComputeSum< ComputeProduct< D1< F, IndexedArg >, D0< G > >,
26  ComputeProduct< D0< F >, D1< G, IndexedArg > > >;
27 
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 > > >;
33 
34  template < class IndexedArgX, class IndexedArgY, class IndexedArgZ >
35  using D3Type =
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 > > >;
44 
45  public:
51  constexpr Product( const F& f_, const G& g_ )
52  : f( f_ ), g( g_ ), value( multiply_via_traits( f(), g() ) )
53  {
54  }
55 
61  constexpr Product( const F& f_, G&& g_ )
62  : f( f_ ), g( std::move( g_ ) ), value( multiply_via_traits( f(), g() ) )
63  {
64  }
65 
71  constexpr Product( F&& f_, const G& g_ )
72  : f( std::move( f_ ) ), g( g_ ), value( multiply_via_traits( f(), g() ) )
73  {
74  }
75 
81  constexpr Product( F&& f_, G&& g_ )
82  : f( std::move( f_ ) ), g( std::move( g_ ) ), value( multiply_via_traits( f(), g() ) )
83  {
84  }
85 
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() ) )
97  {
98  }
99 
101  template < class Arg >
102  void update( Arg const& x )
103  {
104  update_if_present( f, x );
105  update_if_present( g, x );
106  value = multiply_via_traits( f(), g() );
107  }
108 
110  template < int index, class Arg >
111  void update( const Arg& x )
112  {
113  update_if_present< index >( f, x );
114  update_if_present< index >( g, x );
115  value = multiply_via_traits( f(), g() );
116  }
117 
118  template < class... IndexedArgs >
119  void bulk_update( IndexedArgs&&... args )
120  {
121  bulk_update_if_present( f, args... );
122  bulk_update_if_present( g, std::forward< IndexedArgs >( args )... );
123  value = multiply_via_traits( f(), g() );
124  }
125 
127  constexpr decltype( auto ) d0() const noexcept
128  {
129  return value;
130  }
131 
136  template < int id, class Arg, class IndexedArg = IndexedType< Arg, id > >
137  auto d1( Arg const& dx ) const requires( D1Type< IndexedArg >::present )
138  {
139  return sum( product( D1< F, IndexedArg >( f, dx ), D0< G >( g ) ),
140  product( D0< F >( f ), D1< G, IndexedArg >( g, dx ) ) )();
141  }
142 
148  template < int idx, int idy, class ArgX, class ArgY,
149  class IndexedArgX = IndexedType< ArgX, idx >,
150  class IndexedArgY = IndexedType< ArgY, idy > >
151  auto d2( ArgX const& dx, ArgY const& dy ) const
152  requires( D2Type< IndexedArgX, IndexedArgY >::present )
153  {
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 ) ) )();
158  }
159 
166  template < int idx, int idy, int idz, class ArgX, class ArgY, class ArgZ,
167  class IndexedArgX = IndexedType< ArgX, idx >,
168  class IndexedArgY = IndexedType< ArgY, idy >,
169  class IndexedArgZ = IndexedType< ArgZ, idz > >
170  auto d3( ArgX const& dx, ArgY const& dy, ArgZ const& dz ) const
171  requires( D3Type< IndexedArgX, IndexedArgY, IndexedArgZ >::present )
172  {
173  return sum( product( D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >( f, dx, dy, dz ),
174  D0< G >( g ) ),
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 ) ) )();
189  }
190 
191  private:
192  F f;
193  G g;
194  decay_t< decltype( multiply_via_traits( std::declval< F >()(), std::declval< G >()() ) ) >
195  value;
196  };
197 } // namespace funcy::mathop
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