1 //=================================================================================================
2 /*!
3 // \file blaze/math/expressions/DMatVarExpr.h
4 // \brief Header file for the dense matrix variance expression
5 //
6 // Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 // This file is part of the Blaze library. You can redistribute it and/or modify it under
9 // the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 // forms, with or without modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright notice, this list of
14 // conditions and the following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
16 // of conditions and the following disclaimer in the documentation and/or other materials
17 // provided with the distribution.
18 // 3. Neither the names of the Blaze development group nor the names of its contributors
19 // may be used to endorse or promote products derived from this software without specific
20 // prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 */
33 //=================================================================================================
34
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATVAREXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATVAREXPR_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <blaze/math/Exception.h>
44 #include <blaze/math/dense/UniformMatrix.h>
45 #include <blaze/math/dense/UniformVector.h>
46 #include <blaze/math/expressions/DenseMatrix.h>
47 #include <blaze/math/functors/Pow2.h>
48 #include <blaze/math/ReductionFlag.h>
49 #include <blaze/math/shims/Invert.h>
50 #include <blaze/math/typetraits/IsUniform.h>
51 #include <blaze/math/typetraits/UnderlyingBuiltin.h>
52 #include <blaze/util/FunctionTrace.h>
53 #include <blaze/util/IntegralConstant.h>
54 #include <blaze/util/MaybeUnused.h>
55 #include <blaze/util/StaticAssert.h>
56 #include <blaze/util/Types.h>
57
58
59 namespace blaze {
60
61 //=================================================================================================
62 //
63 // GLOBAL FUNCTIONS
64 //
65 //=================================================================================================
66
67 //*************************************************************************************************
68 /*! \cond BLAZE_INTERNAL */
69 /*!\brief Backend implementation of the \c var() function for general dense matrices.
70 // \ingroup dense_matrix
71 //
72 // \param dm The given general dense matrix for the variance computation.
73 // \return The variance of the given matrix.
74 */
75 template< typename MT // Type of the dense matrix
76 , bool SO > // Storage order
decltype(auto)77 inline decltype(auto) var_backend( const DenseMatrix<MT,SO>& dm, FalseType )
78 {
79 using BT = UnderlyingBuiltin_t<MT>;
80
81 BLAZE_INTERNAL_ASSERT( size( *dm ) > 1UL, "Invalid matrix size detected" );
82
83 const auto m( uniform<SO>( rows( *dm ), columns( *dm ), mean( *dm ) ) );
84
85 return sum( map( (*dm) - m, Pow2() ) ) * inv( BT( size( *dm )-1UL ) );
86 }
87 /*! \endcond */
88 //*************************************************************************************************
89
90
91 //*************************************************************************************************
92 /*! \cond BLAZE_INTERNAL */
93 /*!\brief Backend implementation of the \c var() function for uniform dense matrices.
94 // \ingroup dense_matrix
95 //
96 // \param dm The given uniform dense matrix for the variance computation.
97 // \return The var of the given matrix.
98 */
99 template< typename MT // Type of the dense matrix
100 , bool SO > // Storage order
decltype(auto)101 inline decltype(auto) var_backend( const DenseMatrix<MT,SO>& dm, TrueType )
102 {
103 MAYBE_UNUSED( dm );
104
105 BLAZE_INTERNAL_ASSERT( size( *dm ) > 1UL, "Invalid matrix size detected" );
106
107 return ElementType_t<MT>();
108 }
109 /*! \endcond */
110 //*************************************************************************************************
111
112
113 //*************************************************************************************************
114 /*!\brief Computes the variance for the given dense matrix.
115 // \ingroup dense_matrix
116 //
117 // \param dm The given dense matrix for the variance computation.
118 // \return The variance of the given matrix.
119 // \exception std::invalid_argument Invalid input matrix.
120 //
121 // This function computes the <a href="https://en.wikipedia.org/wiki/Variance">variance</a> for
122 // the given dense matrix \a dm. Example:
123
124 \code
125 using blaze::DynamicMatrix;
126
127 DynamicMatrix<int> A{ { 1, 3, 2 }
128 , { 2, 6, 4 }
129 , { 9, 6, 3 } };
130
131 const double v = var( A ); // Results in 6.5
132 \endcode
133
134 // In case the size of the given matrix is smaller than 2, a \a std::invalid_argument is thrown.
135 */
136 template< typename MT // Type of the dense matrix
137 , bool SO > // Storage order
decltype(auto)138 inline decltype(auto) var( const DenseMatrix<MT,SO>& dm )
139 {
140 BLAZE_FUNCTION_TRACE;
141
142 if( size( *dm ) < 2UL ) {
143 BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix" );
144 }
145
146 return var_backend( *dm, IsUniform<MT>() );
147 }
148 //*************************************************************************************************
149
150
151 //*************************************************************************************************
152 /*! \cond BLAZE_INTERNAL */
153 /*!\brief Backend implementation of the row-/column-wise \c var() function for general dense matrices.
154 // \ingroup dense_matrix
155 //
156 // \param dm The given general dense matrix for the variance computation.
157 // \return The row-/column-wise variance of the given matrix.
158 */
159 template< ReductionFlag RF // Reduction flag
160 , typename MT // Type of the dense matrix
161 , bool SO > // Storage order
decltype(auto)162 decltype(auto) var_backend( const DenseMatrix<MT,SO>& dm, FalseType )
163 {
164 using BT = UnderlyingBuiltin_t<MT>;
165
166 const size_t n( RF == rowwise ? columns( *dm ) : rows( *dm ) );
167
168 BLAZE_INTERNAL_ASSERT( n > 1UL, "Invalid matrix size detected" );
169
170 const auto m( expand( mean<RF>( *dm ), n ) );
171
172 return sum<RF>( map( (*dm) - m, Pow2() ) ) * inv( BT( n-1UL ) );
173 }
174 /*! \endcond */
175 //*************************************************************************************************
176
177
178 //*************************************************************************************************
179 /*! \cond BLAZE_INTERNAL */
180 /*!\brief Backend implementation of the row-/column-wise \c var() function for uniform dense matrices.
181 // \ingroup dense_matrix
182 //
183 // \param dm The given general dense matrix for the variance computation.
184 // \return The row-/column-wise variance of the given matrix.
185 */
186 template< ReductionFlag RF // Reduction flag
187 , typename MT // Type of the dense matrix
188 , bool SO > // Storage order
decltype(auto)189 decltype(auto) var_backend( const DenseMatrix<MT,SO>& dm, TrueType )
190 {
191 const size_t n( RF == rowwise ? rows( *dm ) : columns( *dm ) );
192
193 BLAZE_INTERNAL_ASSERT( n > 0UL, "Invalid matrix size detected" );
194
195 constexpr bool TF( ( RF == rowwise ? columnVector : rowVector ) );
196
197 return uniform<TF>( n, ElementType_t<MT>() );
198 }
199 /*! \endcond */
200 //*************************************************************************************************
201
202
203 //*************************************************************************************************
204 /*!\brief Computes the row-/column-wise variance function for the given dense matrix.
205 // \ingroup dense_matrix
206 //
207 // \param dm The given dense matrix for the variance computation.
208 // \return The row-/column-wise variance of the given matrix.
209 // \exception std::invalid_argument Invalid input matrix.
210 //
211 // This function computes the row-/column-wise
212 // <a href="https://en.wikipedia.org/wiki/Variance">variance</a> for the given dense matrix
213 // \a dm. In case \a RF is set to \a rowwise, the function returns a column vector containing
214 // the variance of each row of \a dm. In case \a RF is set to \a columnwise, the function
215 // returns a row vector containing the variance of each column of \a dm. Example:
216
217 \code
218 using blaze::DynamicMatrix;
219 using blaze::DynamicVector;
220 using blaze::columnVector;
221 using blaze::rowVector;
222
223 DynamicMatrix<int> A{ { 1, 3, 2 }
224 , { 2, 6, 4 }
225 , { 9, 6, 3 } };
226
227 DynamicVector<double,columnVector> rv;
228 DynamicVector<double,rowVector> cv;
229
230 rv = var<rowwise>( A ); // Results in ( 1 4 9 )
231 cv = var<columnwise>( A ); // Results in ( 19 3 1 )
232 \endcode
233
234 // In case \a RF is set to \a rowwise and the number of columns of the given matrix is smaller
235 // than 2 or in case \a RF is set to \a columnwise and the number of rows of the given matrix is
236 // smaller than 2, a \a std::invalid_argument is thrown.
237 */
238 template< ReductionFlag RF // Reduction flag
239 , typename MT // Type of the dense matrix
240 , bool SO > // Storage order
decltype(auto)241 inline decltype(auto) var( const DenseMatrix<MT,SO>& dm )
242 {
243 BLAZE_FUNCTION_TRACE;
244
245 BLAZE_STATIC_ASSERT_MSG( RF < 2UL, "Invalid reduction flag" );
246
247 const size_t n( RF == rowwise ? columns( *dm ) : rows( *dm ) );
248
249 if( n < 2UL ) {
250 BLAZE_THROW_INVALID_ARGUMENT( "Invalid input matrix" );
251 }
252
253 return var_backend<RF>( *dm, IsUniform<MT>() );
254 }
255 //*************************************************************************************************
256
257 } // namespace blaze
258
259 #endif
260