funcy  1.6.1
dot.h
1 #pragma once
2 
3 #include <funcy/concepts.h>
4 #include <funcy/util/chainer.h>
5 #include <funcy/util/compute_dot.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 Dot : Chainer< Dot< F, G > >
22  {
23  private:
24  template < class IndexedArg >
25  using D1Type = ComputeSum< ComputeDot< D1< F, IndexedArg >, D0< G > >,
26  ComputeDot< D0< F >, D1< G, IndexedArg > > >;
27 
28  template < class IndexedArgX, class IndexedArgY >
29  using D2Type = ComputeSum< ComputeDot< D2< F, IndexedArgX, IndexedArgY >, D0< G > >,
30  ComputeDot< D1< F, IndexedArgX >, D1< G, IndexedArgY > >,
31  ComputeDot< D1< F, IndexedArgY >, D1< G, IndexedArgX > >,
32  ComputeDot< D0< F >, D2< G, IndexedArgX, IndexedArgY > > >;
33 
34  template < class IndexedArgX, class IndexedArgY, class IndexedArgZ >
35  using D3Type =
36  ComputeSum< ComputeDot< D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >, D0< G > >,
37  ComputeDot< D2< F, IndexedArgX, IndexedArgY >, D1< G, IndexedArgZ > >,
38  ComputeDot< D2< F, IndexedArgX, IndexedArgZ >, D1< G, IndexedArgY > >,
39  ComputeDot< D1< F, IndexedArgX >, D2< G, IndexedArgY, IndexedArgZ > >,
40  ComputeDot< D2< F, IndexedArgY, IndexedArgZ >, D1< G, IndexedArgX > >,
41  ComputeDot< D1< F, IndexedArgY >, D2< G, IndexedArgX, IndexedArgZ > >,
42  ComputeDot< D1< F, IndexedArgZ >, D2< G, IndexedArgX, IndexedArgY > >,
43  ComputeDot< D0< F >, D3< G, IndexedArgX, IndexedArgY, IndexedArgZ > > >;
44 
45  using ReturnType =
46  decay_t< decltype( std::declval< F >()().dot( std::declval< G >()() ) ) >;
47 
48  public:
54  constexpr Dot( F&& f_, G&& g_ )
55  : f( std::move( f_ ) ), g( std::move( g_ ) ), value( f().dot( g() ) )
56  {
57  }
58 
64  constexpr Dot( F&& f_, const G& g_ )
65  : f( std::move( f_ ) ), g( g_ ), value( f().dot( g() ) )
66  {
67  }
68 
74  constexpr Dot( const F& f_, G&& g_ )
75  : f( f_ ), g( std::move( g_ ) ), value( f().dot( g() ) )
76  {
77  }
78 
84  constexpr Dot( const F& f_, const G& g_ ) : f( f_ ), g( g_ ), value( f().dot( g() ) )
85  {
86  }
87 
93  template < class InitF, class InitG >
94  constexpr Dot( InitF&& f_, InitG&& g_ ) requires(
95  std::is_constructible_v< F, std::decay_t< InitF > >&&
96  std::is_constructible_v< G, std::decay_t< InitG > > )
97  : f( std::forward< InitF >( f_ ) ), g( std::forward< InitG >( g_ ) ),
98  value( f().dot( g() ) )
99  {
100  }
101 
103  template < class Arg >
104  void update( Arg const& x )
105  {
106  update_if_present( f, x );
107  update_if_present( g, x );
108  value = f().dot( g() );
109  }
110 
112  template < int index, class Arg >
113  void update( const Arg& x )
114  {
115  update_if_present< index >( f, x );
116  update_if_present< index >( g, x );
117  value = f().dot( g() );
118  }
119 
121  constexpr decltype( auto ) d0() const noexcept
122  {
123  return value;
124  }
125 
130  template < int id, class Arg, class IndexedArg = IndexedType< Arg, id > >
131  ReturnType d1( Arg const& dx ) const requires( D1Type< IndexedArg >::present )
132  {
133  return sum( dot_impl( D1< F, IndexedArg >( f, dx ), D0< G >( g ) ),
134  dot_impl( D0< F >( f ), D1< G, IndexedArg >( g, dx ) ) )();
135  }
136 
142  template < int idx, int idy, class ArgX, class ArgY,
143  class IndexedArgX = IndexedType< ArgX, idx >,
144  class IndexedArgY = IndexedType< ArgY, idy > >
145  ReturnType d2( ArgX const& dx, ArgY const& dy ) const
146  requires( D2Type< IndexedArgX, IndexedArgY >::present )
147  {
148  return sum(
149  dot_impl( D2< F, IndexedArgX, IndexedArgY >( f, dx, dy ), D0< G >( g ) ),
150  dot_impl( D1< F, IndexedArgX >( f, dx ), D1< G, IndexedArgY >( g, dy ) ),
151  dot_impl( D1< F, IndexedArgY >( f, dy ), D1< G, IndexedArgX >( g, dx ) ),
152  dot_impl( D0< F >( f ), D2< G, IndexedArgX, IndexedArgY >( g, dx, dy ) ) )();
153  }
154 
161  template < int idx, int idy, int idz, class ArgX, class ArgY, class ArgZ,
162  class IndexedArgX = IndexedType< ArgX, idx >,
163  class IndexedArgY = IndexedType< ArgY, idy >,
164  class IndexedArgZ = IndexedType< ArgZ, idz > >
165  ReturnType d3( ArgX const& dx, ArgY const& dy, ArgZ const& dz ) const
166  requires( D3Type< IndexedArgX, IndexedArgY, IndexedArgZ >::present )
167  {
168  return sum( dot_impl( D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >( f, dx, dy, dz ),
169  D0< G >( g ) ),
170  dot_impl( D2< F, IndexedArgX, IndexedArgY >( f, dx, dy ),
171  D1< G, IndexedArgZ >( g, dz ) ),
172  dot_impl( D2< F, IndexedArgX, IndexedArgZ >( f, dx, dz ),
173  D1< G, IndexedArgY >( g, dy ) ),
174  dot_impl( D1< F, IndexedArgX >( f, dx ),
175  D2< G, IndexedArgY, IndexedArgZ >( g, dy, dz ) ),
176  dot_impl( D2< F, IndexedArgY, IndexedArgZ >( f, dy, dz ),
177  D1< G, IndexedArgX >( g, dx ) ),
178  dot_impl( D1< F, IndexedArgY >( f, dy ),
179  D2< G, IndexedArgX, IndexedArgZ >( g, dx, dz ) ),
180  dot_impl( D1< F, IndexedArgZ >( f, dz ),
181  D2< G, IndexedArgX, IndexedArgY >( g, dx, dy ) ),
182  dot_impl( D0< F >( f ), D3< G, IndexedArgX, IndexedArgY, IndexedArgZ >(
183  g, dx, dy, dz ) ) )();
184  }
185 
186  private:
187  F f;
188  G g;
189  ReturnType value;
190  };
191 } // namespace funcy::mathop
ReturnType d3(ArgX const &dx, ArgY const &dy, ArgZ const &dz) const requires(D3Type< IndexedArgX
Third directional derivative.
auto dot(F &&f, G &&g)
overload of "dot"-function for the generation of functions.
Definition: generate.h:117
Dot of functions of type F and G.
Definition: dot.h:21
constexpr Dot(const F &f_, const G &g_)
Constructor passing arguments to function constructors.
Definition: dot.h:84
constexpr Dot(const F &f_, G &&g_)
Constructor passing arguments to function constructors.
Definition: dot.h:74
ReturnType d2(ArgX const &dx, ArgY const &dy) const requires(D2Type< IndexedArgX
Second directional derivative.
void update(Arg const &x)
Update point of evaluation.
Definition: dot.h:104
void update(const Arg &x)
Update variable corresponding to index.
Definition: dot.h:113
Mathematical operations and corresponding differentation rules.
ReturnType d1(Arg const &dx) const requires(D1Type< IndexedArg >
First directional derivative.
Definition: dot.h:131
typename Decay< std::decay_t< F > >::type decay_t
Access underlying type (if it is hidden by expression templates).
Definition: type_traits.h:47
Definition: type_traits.h:54
constexpr Dot(F &&f_, G &&g_)
Constructor passing arguments to function constructors.
Definition: dot.h:54
constexpr Dot(F &&f_, const G &g_)
Constructor passing arguments to function constructors.
Definition: dot.h:64
constexpr Dot(InitF &&f_, InitG &&g_) requires(std
Constructor passing arguments to function constructors.
Definition: dot.h:94