funcy  1.6.1
chain.h
1 #pragma once
2 
3 #include <funcy/concepts.h>
4 #include <funcy/util/compute_chain.h>
5 #include <funcy/util/compute_sum.h>
6 #include <funcy/util/derivative_wrappers.h>
7 #include <funcy/util/evaluate_if_present.h>
8 #include <funcy/util/type_traits.h>
9 
10 #include <utility>
11 
12 namespace funcy
13 {
15  template < class >
16  struct Chainer;
18 
19  namespace mathop
20  {
26  template < Function F, Function G >
27  struct Chain : Chainer< Chain< F, G > >
28  {
29  private:
30  using FArg = decltype( std::declval< G >()() );
31 
32  template < class IndexedArgX, class IndexedArgY, class IndexedFArgX,
33  class IndexedFArgY >
34  using D2LazyType =
35  ComputeSum< ComputeChainD2< F, D1< G, IndexedArgX >, D1< G, IndexedArgY >,
36  IndexedFArgX, IndexedFArgY >,
37  ComputeChainD1< F, D2< G, IndexedArgX, IndexedArgY >, IndexedFArgX > >;
38 
39  template < class IndexedArgX, class IndexedArgY, class IndexedArgZ, class IndexedFArgX,
40  class IndexedFArgY, class IndexedFArgZ >
41  using D3LazyType = ComputeSum<
42  ComputeChainD3< F, D1< G, IndexedArgX >, D1< G, IndexedArgY >, D1< G, IndexedArgZ >,
43  IndexedFArgX, IndexedFArgY, IndexedFArgZ >,
44  ComputeChainD2< F, D2< G, IndexedArgX, IndexedArgZ >, D1< G, IndexedArgY >,
45  IndexedFArgX, IndexedFArgY >,
46  ComputeChainD2< F, D1< G, IndexedArgX >, D2< G, IndexedArgY, IndexedArgZ >,
47  IndexedFArgX, IndexedFArgY >,
48  ComputeChainD2< F, D2< G, IndexedArgX, IndexedArgY >, D1< G, IndexedArgZ >,
49  IndexedFArgX, IndexedFArgZ >,
50  ComputeChainD1< F, D3< G, IndexedArgX, IndexedArgY, IndexedArgZ >, IndexedFArgX > >;
51 
52  public:
58  constexpr Chain( const F& f_, const G& g_ ) : g( g_ ), f( f_ )
59  {
60  update_if_present( f, g() );
61  }
62 
68  constexpr Chain( const F& f_, G&& g_ ) : g( std::move( g_ ) ), f( f_ )
69  {
70  update_if_present( f, g() );
71  }
72 
78  constexpr Chain( F&& f_, const G& g_ ) : g( g_ ), f( std::move( f_ ) )
79  {
80  update_if_present( f, g() );
81  }
82 
88  constexpr Chain( F&& f_, G&& g_ ) : g( std::move( g_ ) ), f( std::move( f_ ) )
89  {
90  update_if_present( f, g() );
91  }
92 
94  template < class Arg >
95  void update( const Arg& x )
96  {
97  update_if_present( g, x );
98  update_if_present( f, g() );
99  }
100 
102  template < int index, class Arg >
103  void update( const Arg& x )
104  {
105  update_if_present< index >( g, x );
106  update_if_present( f, g() );
107  }
108 
109  template < class... IndexedArgs >
110  void bulk_update( IndexedArgs&&... args )
111  {
112  bulk_update_if_present( g, std::forward< IndexedArgs >( args )... );
113  update_if_present( f, g() );
114  }
115 
117  constexpr decltype( auto ) d0() const noexcept
118  {
119  return f();
120  }
121 
126  template < int id, class Arg, class IndexedArg = IndexedType< Arg, id >,
127  class IndexedFArg = IndexedType< FArg, id > >
128  auto d1( Arg const& dx ) const
129  requires( ComputeChainD1< F, D1< G, IndexedArg >, IndexedFArg >::present )
130  {
131  return chain< IndexedFArg >( f, D1< G, IndexedArg >( g, dx ) )();
132  }
133 
139  template < int idx, int idy, class ArgX, class ArgY,
140  class IndexedArgX = IndexedType< ArgX, idx >,
141  class IndexedArgY = IndexedType< ArgY, idy >,
142  class IndexedFArgX = IndexedType< FArg, idx >,
143  class IndexedFArgY = IndexedType< FArg, idy > >
144  auto d2( ArgX const& dx, ArgY const& dy ) const requires(
145  D2LazyType< IndexedArgX, IndexedArgY, IndexedFArgX, IndexedFArgY >::present )
146  {
147  return sum(
148  chain< IndexedFArgX, IndexedFArgY >( f, D1< G, IndexedArgX >( g, dx ),
149  D1< G, IndexedArgY >( g, dy ) ),
150  chain< IndexedFArgX >( f, D2< G, IndexedArgX, IndexedArgY >( g, dx, dy ) ) )();
151  }
152 
159  template < int idx, int idy, int idz, class ArgX, class ArgY, class ArgZ,
160  class IndexedArgX = IndexedType< ArgX, idx >,
161  class IndexedArgY = IndexedType< ArgY, idy >,
162  class IndexedArgZ = IndexedType< ArgZ, idz >,
163  class IndexedFArgX = IndexedType< FArg, idx >,
164  class IndexedFArgY = IndexedType< FArg, idy >,
165  class IndexedFArgZ = IndexedType< FArg, idz > >
166  auto d3( ArgX const& dx, ArgY const& dy, ArgZ const& dz ) const
167  requires( D3LazyType< IndexedArgX, IndexedArgY, IndexedArgZ, IndexedFArgX,
168  IndexedFArgY, IndexedFArgZ >::present )
169  {
170  D1< G, IndexedArgX > dGdx( g, dx );
171  D1< G, IndexedArgY > dGdy( g, dy );
172  D1< G, IndexedArgZ > dGdz( g, dz );
173  return sum(
174  chain< IndexedFArgX, IndexedFArgY, IndexedFArgZ >( f, dGdx, dGdy, dGdz ),
175  chain< IndexedFArgX, IndexedFArgY >(
176  f, D2< G, IndexedArgX, IndexedArgZ >( g, dx, dz ), dGdy ),
177  chain< IndexedFArgX, IndexedFArgY >(
178  f, dGdx, D2< G, IndexedArgY, IndexedArgZ >( g, dy, dz ) ),
179  chain< IndexedFArgX, IndexedFArgZ >(
180  f, D2< G, IndexedArgX, IndexedArgY >( g, dx, dy ), dGdz ),
181  chain< IndexedFArgX >(
182  f, D3< G, IndexedArgX, IndexedArgY, IndexedArgZ >( g, dx, dy, dz ) ) )();
183  }
184 
185  private:
186  G g;
187  F f;
188  };
189  } // namespace mathop
190 } // namespace funcy
void update(const Arg &x)
Update point of evaluation.
Definition: chain.h:95
constexpr Chain(F &&f_, G &&g_)
Constructor taking moving the functions to be chained.
Definition: chain.h:88
auto d2(ArgX const &dx, ArgY const &dy) const requires(D2LazyType< IndexedArgX
Second directional derivative.
void update(const Arg &x)
Update variable corresponding to index.
Definition: chain.h:103
Main namespace of the funcy library.
auto d1(Arg const &dx) const requires(ComputeChainD1< F
First directional derivative.
constexpr Chain(const F &f_, const G &g_)
Constructor taking copies of the functions to be chained.
Definition: chain.h:58
auto d3(ArgX const &dx, ArgY const &dy, ArgZ const &dz) const requires(D3LazyType< IndexedArgX
Third directional derivative.
Definition: type_traits.h:54
Chain of functions and of type F resp. G.
Definition: chain.h:27
constexpr Chain(F &&f_, const G &g_)
Constructor taking moving the functions to be chained.
Definition: chain.h:78
constexpr Chain(const F &f_, G &&g_)
Constructor taking moving the functions to be chained.
Definition: chain.h:68