funcy  1.6.1
max.h
1 #pragma once
2 
3 #include <funcy/concepts.h>
4 #include <funcy/constant.h>
5 #include <funcy/util/compute_conditional.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 <type_traits>
11 
12 namespace funcy
13 {
17  namespace mathop
18  {
26  template < Function F, Function G >
27  struct Max
28  {
30  explicit Max( const F& f, const G& g ) : f_( f ), g_( g )
31  {
32  update_value();
33  }
34 
36  template < class Arg >
37  void update( Arg&& x )
38  {
39  update_if_present( f_, x );
40  update_if_present( g_, x );
41  update_value();
42  }
43 
45  template < int index, class Arg >
46  void update( Arg&& x )
47  {
48  update_if_present< index >( f_, x );
49  update_if_present< index >( g_, x );
50  update_value();
51  }
52 
53  template < class... IndexedArgs >
54  void bulk_update( IndexedArgs&&... args )
55  {
56  bulk_update_if_present( f_, args... );
57  bulk_update_if_present( g_, std::forward< IndexedArgs >( args )... );
58  update_value();
59  }
60 
62  double operator()() const noexcept
63  {
64  return value_;
65  }
66 
68  template < int id, class Arg,
69  class IndexedArg = IndexedType< std::decay_t< Arg >, id > >
70  auto d1( Arg&& dx ) const
71  requires( ComputeConditional< D1< F, IndexedArg >, D1< G, IndexedArg > >::present )
72  {
73  using D1F = D1< F, IndexedArg >;
74  using D1G = D1< G, IndexedArg >;
75  return ComputeConditional< D1F, D1G >( D1F( f_, dx ), D1G( g_, dx ),
76  f_bigger_than_g_ )();
77  }
78 
80  template < int idx, int idy, class ArgX, class ArgY,
81  class IndexedArgX = IndexedType< std::decay_t< ArgX >, idx >,
82  class IndexedArgY = IndexedType< std::decay_t< ArgY >, idy > >
83  auto d2( ArgX&& dx, ArgY&& dy ) const
84  requires( ComputeConditional< D2< F, IndexedArgX, IndexedArgY >,
85  D2< G, IndexedArgX, IndexedArgY > >::present )
86  {
87  using D2F = D2< F, IndexedArgX, IndexedArgY >;
88  using D2G = D2< G, IndexedArgX, IndexedArgY >;
89  return ComputeConditional< D2F, D2G >( D2F( f_, dx, dy ), D2G( g_, dx, dy ),
90  f_bigger_than_g_ )();
91  }
92 
94  template < int idx, int idy, int idz, class ArgX, class ArgY, class ArgZ,
95  class IndexedArgX = IndexedType< std::decay_t< ArgX >, idx >,
96  class IndexedArgY = IndexedType< std::decay_t< ArgY >, idy >,
97  class IndexedArgZ = IndexedType< std::decay_t< ArgZ >, idz > >
98  auto d3( ArgX&& dx, ArgY&& dy, ArgZ&& dz ) const requires(
99  ComputeConditional< D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >,
100  D3< G, IndexedArgX, IndexedArgY, IndexedArgZ > >::present )
101  {
102  using D3F = D3< F, IndexedArgX, IndexedArgY, IndexedArgZ >;
103  using D3G = D3< G, IndexedArgX, IndexedArgY, IndexedArgZ >;
104  return ComputeConditional< D3F, D3G >( D3F( f_, dx, dy, dz ), D3G( g_, dx, dy, dz ),
105  f_bigger_than_g_ )();
106  }
107 
108  private:
109  void update_value()
110  {
111  const auto x = f_();
112  const auto y = g_();
113  f_bigger_than_g_ = x > y;
114  value_ = f_bigger_than_g_ ? x : y;
115  }
116  F f_;
117  G g_;
119  bool f_bigger_than_g_;
120  };
121  } // namespace mathop
122 
123  template < Function F, Function G >
124  decltype( auto ) max( F&& f, G&& g )
125  {
126  return mathop::Max< std::decay_t< F >, std::decay_t< G > >( std::forward< F >( f ),
127  std::forward< G >( g ) );
128  }
129 
130  template < Function F, class G >
131  decltype( auto ) max( F&& f, G&& g ) requires( !Function< G > )
132  {
134  std::forward< F >( f ), constant( std::forward< G >( g ) ) );
135  }
136 
137  template < class F, Function G >
138  decltype( auto ) max( F&& f, G&& g ) requires( !Function< F > )
139  {
140  return mathop::Max< Constant< std::decay_t< F > >, std::decay_t< G > >(
141  constant( std::forward< F >( f ) ), std::forward< G >( g ) );
142  }
144 } // namespace funcy
max function .
Definition: max.h:27
Max(const F &f, const G &g)
Constructor.
Definition: max.h:30
Main namespace of the funcy library.
constexpr auto constant(Arg &&x) noexcept((std::is_rvalue_reference_v< Arg > &&std::is_nothrow_move_constructible_v< Arg >)||(std::is_lvalue_reference_v< Arg > &&std::is_nothrow_copy_constructible_v< Arg >))
Wrap a constant.
Definition: constant.h:51
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
Wrap a constant.
Definition: constant.h:10
double operator()() const noexcept
Function value.
Definition: max.h:62
void update(Arg &&x)
Update point of evaluation.
Definition: max.h:37
auto d2(ArgX &&dx, ArgY &&dy) const requires(ComputeConditional< D2< F
Second directional derivative.
auto d1(Arg &&dx) const requires(ComputeConditional< D1< F
First directional derivative.
auto d3(ArgX &&dx, ArgY &&dy, ArgZ &&dz) const requires(ComputeConditional< D3< F
Third directional derivative.
void update(Arg &&x)
Update variable corresponding to index.
Definition: max.h:46