funcy  1.6.1
frobenius_norm.h
1 #pragma once
2 
3 #include <funcy/cmath/pow.h>
4 #include <funcy/concepts.h>
5 #include <funcy/linalg/at.h>
6 #include <funcy/linalg/concepts.h>
7 #include <funcy/linalg/rows_and_cols.h>
8 #include <funcy/util/chainer.h>
9 
10 #include <type_traits>
11 
12 namespace funcy::linalg
13 {
17  namespace detail
19  {
20  template < ConstantSize Mat >
21  [[nodiscard]] inline auto compute_scalar_product( const Mat& A, const Mat& B )
22  {
23  using Index = decltype( rows< Mat >() );
24  auto result = decltype( at( A, 0, 0 ) ){ 0. };
25  for ( Index i = 0; i < rows< Mat >(); ++i )
26  for ( Index j = 0; j < cols< Mat >(); ++j )
27  result += at( A, i, j ) * at( B, i, j );
28  return result;
29  }
30 
31  template < class Mat >
32  [[nodiscard]] inline auto compute_scalar_product( const Mat& A, const Mat& B )
33  {
34  using Index = decltype( rows( A ) );
35  auto result = decltype( at( A, 0, 0 ) ){ 0. };
36  for ( Index i = 0; i < rows( A ); ++i )
37  for ( Index j = 0; j < cols( A ); ++j )
38  result += at( A, i, j ) * at( B, i, j );
39  return result;
40  }
41  } // namespace detail
43 
46  template < class Mat >
47  struct SquaredFrobeniusNorm : Chainer< SquaredFrobeniusNorm< Mat > >
48  {
49  SquaredFrobeniusNorm() = default;
50 
51  explicit SquaredFrobeniusNorm( const Mat& A ) : A_( A )
52  {
53  value = detail::compute_scalar_product( A_, A_ );
54  }
55 
56  explicit SquaredFrobeniusNorm( Mat&& A ) : A_( std::move( A ) )
57  {
58  value = detail::compute_scalar_product( A_, A_ );
59  }
60 
62  void update( const Mat& A )
63  {
64  A_ = A;
65  value = detail::compute_scalar_product( A_, A_ );
66  }
67 
69  [[nodiscard]] auto d0() const noexcept
70  {
71  return value;
72  }
73 
75  [[nodiscard]] auto d1( const Mat& dA ) const
76  {
77  return 2 * detail::compute_scalar_product( A_, dA );
78  }
79 
81  [[nodiscard]] auto d2( const Mat& dA1, const Mat& dA2 ) const
82  {
83  return 2 * detail::compute_scalar_product( dA1, dA2 );
84  }
85 
86  private:
87  Mat A_;
88  std::decay_t< decltype( at( std::declval< Mat >(), 0, 0 ) ) > value;
89  };
90 
93  template < class Mat >
95 
98  template < class Mat >
99  [[nodiscard]] auto frobenius_norm( const Mat& A )
100  {
101  return FrobeniusNorm( A );
102  }
103 
106  template < Function F >
107  [[nodiscard]] auto frobenius_norm( const F& f )
108  {
109  return FrobeniusNorm( f() )( f );
110  }
112 } // namespace funcy::linalg
auto d0() const noexcept
Squared matrix norm.
Definition: frobenius_norm.h:69
void update(const Mat &A)
Reset matrix to compute squared norm from.
Definition: frobenius_norm.h:62
auto cols(const Mat &A) requires(!ConstantSize< Mat > &&static_check
Number of columns of a dynamic size matrix.
Definition: rows_and_cols.h:36
auto rows(const Mat &A) requires(!ConstantSize< Mat > &&static_check
Number of rows of a dynamic size matrix.
Definition: rows_and_cols.h:13
auto d1(const Mat &dA) const
First directional derivative.
Definition: frobenius_norm.h:75
auto d2(const Mat &dA1, const Mat &dA2) const
Second directional derivative.
Definition: frobenius_norm.h:81
Functionality from linear algebra such as (modified) principal and mixed matrix invariants.
auto frobenius_norm(const Mat &A)
Definition: frobenius_norm.h:99
decltype(auto) FUNCY_ALWAYS_INLINE at(M &&A, Index i, Index j) requires requires(std
Access matrix entry.
Definition: at.h:17
mathop::Chain< Sqrt, SquaredFrobeniusNorm< Mat > > FrobeniusNorm
Definition: frobenius_norm.h:94
Chain of functions and of type F resp. G.
Definition: chain.h:27
Definition: frobenius_norm.h:47