1 //=================================================================================================
2 /*!
3 // \file blaze/math/expressions/DMatNormExpr.h
4 // \brief Header file for the dense matrix norm 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 //x
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_DMATNORMEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATNORMEXPR_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <utility>
44 #include <blaze/math/Aliases.h>
45 #include <blaze/math/expressions/DenseMatrix.h>
46 #include <blaze/math/functors/Abs.h>
47 #include <blaze/math/functors/Bind2nd.h>
48 #include <blaze/math/functors/Cbrt.h>
49 #include <blaze/math/functors/L1Norm.h>
50 #include <blaze/math/functors/L2Norm.h>
51 #include <blaze/math/functors/L3Norm.h>
52 #include <blaze/math/functors/L4Norm.h>
53 #include <blaze/math/functors/LpNorm.h>
54 #include <blaze/math/functors/Noop.h>
55 #include <blaze/math/functors/Pow.h>
56 #include <blaze/math/functors/Pow2.h>
57 #include <blaze/math/functors/Pow3.h>
58 #include <blaze/math/functors/Qdrt.h>
59 #include <blaze/math/functors/SqrAbs.h>
60 #include <blaze/math/functors/Sqrt.h>
61 #include <blaze/math/shims/Evaluate.h>
62 #include <blaze/math/shims/Invert.h>
63 #include <blaze/math/shims/IsZero.h>
64 #include <blaze/math/shims/PrevMultiple.h>
65 #include <blaze/math/SIMD.h>
66 #include <blaze/math/traits/MultTrait.h>
67 #include <blaze/math/typetraits/HasLoad.h>
68 #include <blaze/math/typetraits/HasSIMDAdd.h>
69 #include <blaze/math/typetraits/IsPadded.h>
70 #include <blaze/math/typetraits/IsSIMDEnabled.h>
71 #include <blaze/math/typetraits/UnderlyingBuiltin.h>
72 #include <blaze/system/Optimizations.h>
73 #include <blaze/util/Assert.h>
74 #include <blaze/util/FunctionTrace.h>
75 #include <blaze/util/IntegralConstant.h>
76 #include <blaze/util/mpl/And.h>
77 #include <blaze/util/mpl/If.h>
78 #include <blaze/util/StaticAssert.h>
79 #include <blaze/util/TypeList.h>
80 #include <blaze/util/Types.h>
81 #include <blaze/util/typetraits/HasMember.h>
82 #include <blaze/util/typetraits/RemoveCVRef.h>
83 #include <blaze/util/typetraits/RemoveReference.h>
84
85
86 namespace blaze {
87
88 //=================================================================================================
89 //
90 // CLASS DEFINITION
91 //
92 //=================================================================================================
93
94 //*************************************************************************************************
95 /*! \cond BLAZE_INTERNAL */
96 /*!\brief Auxiliary helper struct for the dense matrix norms.
97 // \ingroup dense_matrix
98 */
99 template< typename MT // Type of the dense matrix
100 , typename Abs // Type of the abs operation
101 , typename Power > // Type of the power operation
102 struct DMatNormHelper
103 {
104 //**Type definitions****************************************************************************
105 //! Element type of the dense matrix expression.
106 using ET = ElementType_t<MT>;
107
108 //! Composite type of the dense matrix expression.
109 using CT = RemoveReference_t< CompositeType_t<MT> >;
110 //**********************************************************************************************
111
112 //**********************************************************************************************
113 static constexpr bool value =
114 ( useOptimizedKernels &&
115 CT::simdEnabled &&
116 If_t< HasSIMDEnabled_v<Abs> && HasSIMDEnabled_v<Power>
117 , And_t< GetSIMDEnabled<Abs,ET>, GetSIMDEnabled<Power,ET> >
118 , And_t< HasLoad<Abs>, HasLoad<Power> > >::value &&
119 HasSIMDAdd_v< ElementType_t<CT>, ElementType_t<CT> > );
120 //**********************************************************************************************
121 };
122 /*! \endcond */
123 //*************************************************************************************************
124
125
126
127
128 //=================================================================================================
129 //
130 // GLOBAL FUNCTIONS
131 //
132 //=================================================================================================
133
134 //*************************************************************************************************
135 /*! \cond BLAZE_INTERNAL */
136 /*!\brief Default backend implementation of the norm of a row-major dense matrix.
137 // \ingroup dense_matrix
138 //
139 // \param dm The given row-major dense matrix for the norm computation.
140 // \param abs The functor for the abs operation.
141 // \param power The functor for the power operation.
142 // \param root The functor for the root operation.
143 // \return The norm of the given matrix.
144 //
145 // This function implements the performance optimized norm of a row-major dense matrix. Due to
146 // the explicit application of the SFINAE principle, this function can only be selected by the
147 // compiler in case vectorization cannot be applied.
148 */
149 template< typename MT // Type of the dense matrix
150 , typename Abs // Type of the abs opertaion
151 , typename Power // Type of the power operation
152 , typename Root > // Type of the root operation
decltype(auto)153 inline decltype(auto) norm_backend( const DenseMatrix<MT,false>& dm, Abs abs, Power power, Root root, FalseType )
154 {
155 using CT = CompositeType_t<MT>;
156 using ET = ElementType_t<MT>;
157 using PT = RemoveCVRef_t< decltype( power( abs( std::declval<ET>() ) ) ) >;
158 using RT = RemoveCVRef_t< decltype( evaluate( root( std::declval<PT>() ) ) ) >;
159
160 if( (*dm).rows() == 0UL || (*dm).columns() == 0UL ) return RT{};
161
162 CT tmp( *dm );
163
164 const size_t M( tmp.rows() );
165 const size_t N( tmp.columns() );
166
167 PT norm( power( abs( tmp(0UL,0UL) ) ) );
168
169 {
170 size_t j( 1UL );
171
172 for( ; (j+4UL) <= N; j+=4UL ) {
173 norm += power( abs( tmp(0UL,j ) ) ) + power( abs( tmp(0UL,j+1UL) ) ) +
174 power( abs( tmp(0UL,j+2UL) ) ) + power( abs( tmp(0UL,j+3UL) ) );
175 }
176 for( ; (j+2UL) <= N; j+=2UL ) {
177 norm += power( abs( tmp(0UL,j) ) ) + power( abs( tmp(0UL,j+1UL) ) );
178 }
179 for( ; j<N; ++j ) {
180 norm += power( abs( tmp(0UL,j) ) );
181 }
182 }
183
184 for( size_t i=1UL; i<M; ++i )
185 {
186 size_t j( 0UL );
187
188 for( ; (j+4UL) <= N; j+=4UL ) {
189 norm += power( abs( tmp(i,j ) ) ) + power( abs( tmp(i,j+1UL) ) ) +
190 power( abs( tmp(i,j+2UL) ) ) + power( abs( tmp(i,j+3UL) ) );
191 }
192 for( ; (j+2UL) <= N; j+=2UL ) {
193 norm += power( abs( tmp(i,j) ) ) + power( abs( tmp(i,j+1UL) ) );
194 }
195 for( ; j<N; ++j ) {
196 norm += power( abs( tmp(i,j) ) );
197 }
198 }
199
200 return evaluate( root( norm ) );
201 }
202 /*! \endcond */
203 //*************************************************************************************************
204
205
206 //*************************************************************************************************
207 /*! \cond BLAZE_INTERNAL */
208 /*!\brief Default backend implementation of the norm of a column-major dense matrix.
209 // \ingroup dense_matrix
210 //
211 // \param dm The given column-major dense matrix for the norm computation.
212 // \param abs The functor for the abs operation.
213 // \param power The functor for the power operation.
214 // \param root The functor for the root operation.
215 // \return The norm of the given matrix.
216 //
217 // This function implements the performance optimized norm of a column-major dense matrix. Due
218 // to the explicit application of the SFINAE principle, this function can only be selected by
219 // the compiler in case vectorization cannot be applied.
220 */
221 template< typename MT // Type of the dense matrix
222 , typename Abs // Type of the abs operation
223 , typename Power // Type of the power operation
224 , typename Root > // Type of the root operation
decltype(auto)225 inline decltype(auto) norm_backend( const DenseMatrix<MT,true>& dm, Abs abs, Power power, Root root, FalseType )
226 {
227 using CT = CompositeType_t<MT>;
228 using ET = ElementType_t<MT>;
229 using PT = RemoveCVRef_t< decltype( power( abs( std::declval<ET>() ) ) ) >;
230 using RT = RemoveCVRef_t< decltype( evaluate( root( std::declval<PT>() ) ) ) >;
231
232 if( (*dm).rows() == 0UL || (*dm).columns() == 0UL ) return RT{};
233
234 CT tmp( *dm );
235
236 const size_t M( tmp.rows() );
237 const size_t N( tmp.columns() );
238
239 PT norm( power( abs( tmp(0UL,0UL) ) ) );
240
241 {
242 size_t i( 1UL );
243
244 for( ; (i+4UL) <= M; i+=4UL ) {
245 norm += power( abs( tmp(i ,0UL) ) ) + power( abs( tmp(i+1UL,0UL) ) ) +
246 power( abs( tmp(i+2UL,0UL) ) ) + power( abs( tmp(i+3UL,0UL) ) );
247 }
248 for( ; (i+2UL) <= M; i+=2UL ) {
249 norm += power( abs( tmp(i,0UL) ) ) + power( abs( tmp(i+1UL,0UL) ) );
250 }
251 for( ; i<M; ++i ) {
252 norm += power( abs( tmp(i,0UL) ) );
253 }
254 }
255
256 for( size_t j=1UL; j<N; ++j )
257 {
258 size_t i( 0UL );
259
260 for( ; (i+4UL) <= M; i+=4UL ) {
261 norm += power( abs( tmp(i ,j) ) ) + power( abs( tmp(i+1UL,j) ) ) +
262 power( abs( tmp(i+2UL,j) ) ) + power( abs( tmp(i+3UL,j) ) );
263 }
264 for( ; (i+2UL) <= M; i+=2UL ) {
265 norm += power( abs( tmp(i,j) ) ) + power( abs( tmp(i+1UL,j) ) );
266 }
267 for( ; i<M; ++i ) {
268 norm += power( abs( tmp(i,j) ) );
269 }
270 }
271
272 return evaluate( root( norm ) );
273 }
274 /*! \endcond */
275 //*************************************************************************************************
276
277
278 //*************************************************************************************************
279 /*! \cond BLAZE_INTERNAL */
280 /*!\brief SIMD optimized backend implementation of the norm of a row-major dense matrix.
281 // \ingroup dense_matrix
282 //
283 // \param dm The given row-major dense matrix for the norm computation.
284 // \param abs The functor for the abs operation.
285 // \param power The functor for the power operation.
286 // \param root The functor for the root operation.
287 // \return The norm of the given matrix.
288 //
289 // This function implements the performance optimized norm of a row-major dense matrix. Due to
290 // the explicit application of the SFINAE principle, this function can only be selected by the
291 // compiler in case vectorization can be applied.
292 */
293 template< typename MT // Type of the dense matrix
294 , typename Abs // Type of the abs operation
295 , typename Power // Type of the power operation
296 , typename Root > // Type of the root operation
decltype(auto)297 inline decltype(auto) norm_backend( const DenseMatrix<MT,false>& dm, Abs abs, Power power, Root root, TrueType )
298 {
299 using CT = CompositeType_t<MT>;
300 using ET = ElementType_t<MT>;
301 using RT = decltype( evaluate( root( std::declval<ET>() ) ) );
302
303 static constexpr size_t SIMDSIZE = SIMDTrait<ET>::size;
304
305 if( (*dm).rows() == 0UL || (*dm).columns() == 0UL ) return RT{};
306
307 CT tmp( *dm );
308
309 const size_t M( tmp.rows() );
310 const size_t N( tmp.columns() );
311
312 constexpr bool remainder( !IsPadded_v< RemoveReference_t<CT> > );
313
314 ET norm{};
315
316 if( !remainder || N >= SIMDSIZE )
317 {
318 const size_t jpos( remainder ? prevMultiple( N, SIMDSIZE ) : N );
319 BLAZE_INTERNAL_ASSERT( jpos <= N, "Invalid end calculation" );
320
321 SIMDTrait_t<ET> xmm1{};
322 size_t i( 0UL );
323
324 for( ; (i+4UL) <= M; i+=4UL )
325 {
326 xmm1 += power( abs( tmp.load(i,0UL) ) );
327 SIMDTrait_t<ET> xmm2( power( abs( tmp.load(i+1UL,0UL) ) ) );
328 SIMDTrait_t<ET> xmm3( power( abs( tmp.load(i+2UL,0UL) ) ) );
329 SIMDTrait_t<ET> xmm4( power( abs( tmp.load(i+3UL,0UL) ) ) );
330 size_t j( SIMDSIZE );
331
332 for( ; j<jpos; j+=SIMDSIZE ) {
333 xmm1 += power( abs( tmp.load(i ,j) ) );
334 xmm2 += power( abs( tmp.load(i+1UL,j) ) );
335 xmm3 += power( abs( tmp.load(i+2UL,j) ) );
336 xmm4 += power( abs( tmp.load(i+3UL,j) ) );
337 }
338 for( ; remainder && j<N; ++j ) {
339 norm += power( abs( tmp(i ,j) ) );
340 norm += power( abs( tmp(i+1UL,j) ) );
341 norm += power( abs( tmp(i+2UL,j) ) );
342 norm += power( abs( tmp(i+3UL,j) ) );
343 }
344
345 xmm1 += xmm2;
346 xmm3 += xmm4;
347 xmm1 += xmm3;
348 }
349
350 if( i+2UL <= M )
351 {
352 xmm1 += power( abs( tmp.load(i,0UL) ) );
353 SIMDTrait_t<ET> xmm2( power( abs( tmp.load(i+1UL,0UL) ) ) );
354 size_t j( SIMDSIZE );
355
356 for( ; j<jpos; j+=SIMDSIZE ) {
357 xmm1 += power( abs( tmp.load(i ,j) ) );
358 xmm2 += power( abs( tmp.load(i+1UL,j) ) );
359 }
360 for( ; remainder && j<N; ++j ) {
361 norm += power( abs( tmp(i ,j) ) );
362 norm += power( abs( tmp(i+1UL,j) ) );
363 }
364
365 xmm1 += xmm2;
366
367 i += 2UL;
368 }
369
370 if( i < M )
371 {
372 xmm1 += power( abs( tmp.load(i,0UL) ) );
373 size_t j( SIMDSIZE );
374
375 for( ; j<jpos; j+=SIMDSIZE ) {
376 xmm1 += power( abs( tmp.load(i,j) ) );
377 }
378 for( ; remainder && j<N; ++j ) {
379 norm += power( abs( tmp(i,j) ) );
380 }
381 }
382
383 norm += sum( xmm1 );
384 }
385 else
386 {
387 for( size_t i=0UL; i<M; ++i ) {
388 for( size_t j=0UL; j<N; ++j ) {
389 norm += power( abs( tmp(i,j) ) );
390 }
391 }
392 }
393
394 return evaluate( root( norm ) );
395 }
396 /*! \endcond */
397 //*************************************************************************************************
398
399
400 //*************************************************************************************************
401 /*! \cond BLAZE_INTERNAL */
402 /*!\brief SIMD optimized backend implementation of the norm of a column-major dense matrix.
403 // \ingroup dense_matrix
404 //
405 // \param dm The given column-major dense matrix for the norm computation.
406 // \param abs The functor for the abs operation.
407 // \param power The functor for the power operation.
408 // \param root The functor for the root operation.
409 // \return The norm of the given matrix.
410 //
411 // This function implements the performance optimized norm of a column-major dense matrix. Due
412 // to the explicit application of the SFINAE principle, this function can only be selected by
413 // the compiler in case vectorization can be applied.
414 */
415 template< typename MT // Type of the dense matrix
416 , typename Abs // Type of the abs operation
417 , typename Power // Type of the power operation
418 , typename Root > // Type of the root operation
decltype(auto)419 inline decltype(auto) norm_backend( const DenseMatrix<MT,true>& dm, Abs abs, Power power, Root root, TrueType )
420 {
421 using CT = CompositeType_t<MT>;
422 using ET = ElementType_t<MT>;
423 using RT = decltype( evaluate( root( std::declval<ET>() ) ) );
424
425 static constexpr size_t SIMDSIZE = SIMDTrait<ET>::size;
426
427 if( (*dm).rows() == 0UL || (*dm).columns() == 0UL ) return RT{};
428
429 CT tmp( *dm );
430
431 const size_t M( tmp.rows() );
432 const size_t N( tmp.columns() );
433
434 constexpr bool remainder( !IsPadded_v< RemoveReference_t<CT> > );
435
436 ET norm{};
437
438 if( !remainder || N >= SIMDSIZE )
439 {
440 const size_t ipos( remainder ? prevMultiple( M, SIMDSIZE ) :M );
441 BLAZE_INTERNAL_ASSERT( ipos <= M, "Invalid end calculation" );
442
443 SIMDTrait_t<ET> xmm1{};
444 size_t j( 0UL );
445
446 for( ; (j+4UL) <= N; j+=4UL )
447 {
448 xmm1 += power( abs( tmp.load(0UL,j) ) );
449 SIMDTrait_t<ET> xmm2( power( abs( tmp.load(0UL,j+1UL) ) ) );
450 SIMDTrait_t<ET> xmm3( power( abs( tmp.load(0UL,j+2UL) ) ) );
451 SIMDTrait_t<ET> xmm4( power( abs( tmp.load(0UL,j+3UL) ) ) );
452 size_t i( SIMDSIZE );
453
454 for( ; i<ipos; i+=SIMDSIZE ) {
455 xmm1 += power( abs( tmp.load(i,j ) ) );
456 xmm2 += power( abs( tmp.load(i,j+1UL) ) );
457 xmm3 += power( abs( tmp.load(i,j+2UL) ) );
458 xmm4 += power( abs( tmp.load(i,j+3UL) ) );
459 }
460 for( ; remainder && i<M; ++i ) {
461 norm += power( abs( tmp(i,j ) ) );
462 norm += power( abs( tmp(i,j+1UL) ) );
463 norm += power( abs( tmp(i,j+2UL) ) );
464 norm += power( abs( tmp(i,j+3UL) ) );
465 }
466
467 xmm1 += xmm2;
468 xmm3 += xmm4;
469 xmm1 += xmm3;
470 }
471
472 if( j+2UL <= N )
473 {
474 xmm1 += power( abs( tmp.load(0UL,j) ) );
475 SIMDTrait_t<ET> xmm2( power( abs( tmp.load(0UL,j+1UL) ) ) );
476 size_t i( SIMDSIZE );
477
478 for( ; i<ipos; i+=SIMDSIZE ) {
479 xmm1 += power( abs( tmp.load(i,j ) ) );
480 xmm2 += power( abs( tmp.load(i,j+1UL) ) );
481 }
482 for( ; remainder && i<M; ++i ) {
483 norm += power( abs( tmp(i,j ) ) );
484 norm += power( abs( tmp(i,j+1UL) ) );
485 }
486
487 xmm1 += xmm2;
488
489 j += 2UL;
490 }
491
492 if( j < N )
493 {
494 xmm1 += power( abs( tmp.load(0UL,j) ) );
495 size_t i( SIMDSIZE );
496
497 for( ; i<ipos; i+=SIMDSIZE ) {
498 xmm1 += power( abs( tmp.load(i,j) ) );
499 }
500 for( ; remainder && i<M; ++i ) {
501 norm += power( abs( tmp(i,j) ) );
502 }
503 }
504
505 norm += sum( xmm1 );
506 }
507 else
508 {
509 for( size_t j=0UL; j<N; ++j ) {
510 for( size_t i=0UL; i<M; ++i ) {
511 norm += power( abs( tmp(i,j) ) );
512 }
513 }
514 }
515
516 return evaluate( root( norm ) );
517 }
518 /*! \endcond */
519 //*************************************************************************************************
520
521
522 //*************************************************************************************************
523 /*! \cond BLAZE_INTERNAL */
524 /*!\brief Computes a custom norm for the given dense matrix.
525 // \ingroup dense_matrix
526 //
527 // \param dm The given dense matrix for the norm computation.
528 // \param abs The functor for the abs operation.
529 // \param power The functor for the power operation.
530 // \param root The functor for the root operation.
531 // \return The norm of the given dense matrix.
532 //
533 // This function computes a custom norm of the given dense matrix by means of the given functors.
534 // The following example demonstrates the computation of the L2 norm by means of the blaze::Pow2
535 // and blaze::Sqrt functors:
536
537 \code
538 blaze::DynamicMatrix<double> A;
539 // ... Resizing and initialization
540 const double l2 = norm( A, blaze::Pow2(), blaze::Sqrt() );
541 \endcode
542 */
543 template< typename MT // Type of the dense matrix
544 , bool SO // Storage order
545 , typename Abs // Type of the abs operation
546 , typename Power // Type of the power operation
547 , typename Root > // Type of the root operation
decltype(auto)548 decltype(auto) norm_backend( const DenseMatrix<MT,SO>& dm, Abs abs, Power power, Root root )
549 {
550 return norm_backend( *dm, abs, power, root, Bool_t< DMatNormHelper<MT,Abs,Power>::value >() );
551 }
552 /*! \endcond */
553 //*************************************************************************************************
554
555
556 //*************************************************************************************************
557 /*!\brief Computes the L2 norm for the given dense matrix.
558 // \ingroup dense_matrix
559 //
560 // \param dm The given dense matrix for the norm computation.
561 // \return The L2 norm of the given dense matrix.
562 //
563 // This function computes the L2 norm of the given dense matrix:
564
565 \code
566 blaze::DynamicMatrix<double> A;
567 // ... Resizing and initialization
568 const double l2 = norm( A );
569 \endcode
570 */
571 template< typename MT // Type of the dense matrix
572 , bool SO > // Storage order
decltype(auto)573 decltype(auto) norm( const DenseMatrix<MT,SO>& dm )
574 {
575 BLAZE_FUNCTION_TRACE;
576
577 return norm_backend( *dm, SqrAbs(), Noop(), Sqrt() );
578 }
579 //*************************************************************************************************
580
581
582 //*************************************************************************************************
583 /*!\brief Computes the squared L2 norm for the given dense matrix.
584 // \ingroup dense_matrix
585 //
586 // \param dm The given dense matrix for the norm computation.
587 // \return The squared L2 norm of the given dense matrix.
588 //
589 // This function computes the squared L2 norm of the given dense matrix:
590
591 \code
592 blaze::DynamicMatrix<double> A;
593 // ... Resizing and initialization
594 const double l2 = sqrNorm( A );
595 \endcode
596 */
597 template< typename MT // Type of the dense matrix
598 , bool SO > // Storage order
decltype(auto)599 decltype(auto) sqrNorm( const DenseMatrix<MT,SO>& dm )
600 {
601 BLAZE_FUNCTION_TRACE;
602
603 return norm_backend( *dm, SqrAbs(), Noop(), Noop() );
604 }
605 //*************************************************************************************************
606
607
608 //*************************************************************************************************
609 /*!\brief Computes the L1 norm for the given dense matrix.
610 // \ingroup dense_matrix
611 //
612 // \param dm The given dense matrix for the norm computation.
613 // \return The L1 norm of the given dense matrix.
614 //
615 // This function computes the L1 norm of the given dense matrix:
616
617 \code
618 blaze::DynamicMatrix<double> A;
619 // ... Resizing and initialization
620 const double l1 = l1Norm( A );
621 \endcode
622 */
623 template< typename MT // Type of the dense matrix
624 , bool SO > // Storage order
decltype(auto)625 decltype(auto) l1Norm( const DenseMatrix<MT,SO>& dm )
626 {
627 BLAZE_FUNCTION_TRACE;
628
629 return norm_backend( *dm, Abs(), Noop(), Noop() );
630 }
631 //*************************************************************************************************
632
633
634 //*************************************************************************************************
635 /*!\brief Computes the L2 norm for the given dense matrix.
636 // \ingroup dense_matrix
637 //
638 // \param dm The given dense matrix for the norm computation.
639 // \return The L2 norm of the given dense matrix.
640 //
641 // This function computes the L2 norm of the given dense matrix:
642
643 \code
644 blaze::DynamicMatrix<double> A;
645 // ... Resizing and initialization
646 const double l2 = l2Norm( A );
647 \endcode
648 */
649 template< typename MT // Type of the dense matrix
650 , bool SO > // Storage order
decltype(auto)651 decltype(auto) l2Norm( const DenseMatrix<MT,SO>& dm )
652 {
653 BLAZE_FUNCTION_TRACE;
654
655 return norm_backend( *dm, SqrAbs(), Noop(), Sqrt() );
656 }
657 //*************************************************************************************************
658
659
660 //*************************************************************************************************
661 /*!\brief Computes the L3 norm for the given dense matrix.
662 // \ingroup dense_matrix
663 //
664 // \param dm The given dense matrix for the norm computation.
665 // \return The L3 norm of the given dense matrix.
666 //
667 // This function computes the L3 norm of the given dense matrix:
668
669 \code
670 blaze::DynamicMatrix<double> A;
671 // ... Resizing and initialization
672 const double l3 = l3Norm( A );
673 \endcode
674 */
675 template< typename MT // Type of the dense matrix
676 , bool SO > // Storage order
decltype(auto)677 decltype(auto) l3Norm( const DenseMatrix<MT,SO>& dm )
678 {
679 BLAZE_FUNCTION_TRACE;
680
681 return norm_backend( *dm, Abs(), Pow3(), Cbrt() );
682 }
683 //*************************************************************************************************
684
685
686 //*************************************************************************************************
687 /*!\brief Computes the L4 norm for the given dense matrix.
688 // \ingroup dense_matrix
689 //
690 // \param dm The given dense matrix for the norm computation.
691 // \return The L4 norm of the given dense matrix.
692 //
693 // This function computes the L4 norm of the given dense matrix:
694
695 \code
696 blaze::DynamicMatrix<double> A;
697 // ... Resizing and initialization
698 const double l4 = l4Norm( A );
699 \endcode
700 */
701 template< typename MT // Type of the dense matrix
702 , bool SO > // Storage order
decltype(auto)703 decltype(auto) l4Norm( const DenseMatrix<MT,SO>& dm )
704 {
705 BLAZE_FUNCTION_TRACE;
706
707 return norm_backend( *dm, SqrAbs(), Pow2(), Qdrt() );
708 }
709 //*************************************************************************************************
710
711
712 //*************************************************************************************************
713 /*!\brief Computes the Lp norm for the given dense matrix.
714 // \ingroup dense_matrix
715 //
716 // \param dm The given dense matrix for the norm computation.
717 // \param p The norm parameter (p > 0).
718 // \return The Lp norm of the given dense matrix.
719 //
720 // This function computes the Lp norm of the given dense matrix, where the norm is specified by
721 // the runtime argument \a p:
722
723 \code
724 blaze::DynamicMatrix<double> A;
725 // ... Resizing and initialization
726 const double lp = lpNorm( A, 2.3 );
727 \endcode
728
729 // \note The norm parameter \a p is expected to be larger than 0. This precondition is only checked
730 // by a user assertion.
731 */
732 template< typename MT // Type of the dense matrix
733 , bool SO // Storage order
734 , typename ST > // Type of the norm parameter
decltype(auto)735 decltype(auto) lpNorm( const DenseMatrix<MT,SO>& dm, ST p )
736 {
737 BLAZE_FUNCTION_TRACE;
738
739 BLAZE_USER_ASSERT( !isZero( p ), "Invalid p for Lp norm detected" );
740
741 using ScalarType = MultTrait_t< UnderlyingBuiltin_t<MT>, decltype( inv( p ) ) >;
742 using UnaryPow = Bind2nd<Pow,ScalarType>;
743 return norm_backend( *dm, Abs(), UnaryPow( Pow(), p ), UnaryPow( Pow(), inv( p ) ) );
744 }
745 //*************************************************************************************************
746
747
748 //*************************************************************************************************
749 /*!\brief Computes the Lp norm for the given dense matrix.
750 // \ingroup dense_matrix
751 //
752 // \param dm The given dense matrix for the norm computation.
753 // \return The Lp norm of the given dense matrix.
754 //
755 // This function computes the Lp norm of the given dense matrix, where the norm is specified by
756 // the runtime argument \a P:
757
758 \code
759 blaze::DynamicMatrix<double> A;
760 // ... Resizing and initialization
761 const double lp = lpNorm<2>( A );
762 \endcode
763
764 // \note The norm parameter \a P is expected to be larger than 0. A value of 0 results in a
765 // compile time error!.
766 */
767 template< size_t P // Compile time norm parameter
768 , typename MT // Type of the dense matrix
769 , bool SO > // Storage order
decltype(auto)770 inline decltype(auto) lpNorm( const DenseMatrix<MT,SO>& dm )
771 {
772 BLAZE_STATIC_ASSERT_MSG( P > 0UL, "Invalid norm parameter detected" );
773
774 using Norms = TypeList< L1Norm, L2Norm, L3Norm, L4Norm, LpNorm<P> >;
775 using Norm = typename TypeAt< Norms, min( P-1UL, 4UL ) >::Type;
776
777 return Norm()( *dm );
778 }
779 //*************************************************************************************************
780
781
782 //*************************************************************************************************
783 /*!\brief Computes the infinity norm for the given dense matrix.
784 // \ingroup dense_matrix
785 //
786 // \param dm The given dense matrix for the norm computation.
787 // \return The infinity norm of the given dense matrix.
788 //
789 // This function computes the infinity norm of the given dense matrix:
790
791 \code
792 blaze::DynamicMatrix<double> A;
793 // ... Resizing and initialization
794 const double linf = linfNorm( A );
795 \endcode
796 */
797 template< typename MT // Type of the dense matrix
798 , bool SO > // Storage order
decltype(auto)799 decltype(auto) linfNorm( const DenseMatrix<MT,SO>& dm )
800 {
801 BLAZE_FUNCTION_TRACE;
802
803 return max( abs( *dm ) );
804 }
805 //*************************************************************************************************
806
807
808 //*************************************************************************************************
809 /*!\brief Computes the maximum norm for the given dense matrix.
810 // \ingroup dense_matrix
811 //
812 // \param dm The given dense matrix for the norm computation.
813 // \return The maximum norm of the given dense matrix.
814 //
815 // This function computes the maximum norm of the given dense matrix:
816
817 \code
818 blaze::DynamicMatrix<double> A;
819 // ... Resizing and initialization
820 const double max = maxNorm( A );
821 \endcode
822 */
823 template< typename MT // Type of the dense matrix
824 , bool SO > // Storage order
decltype(auto)825 decltype(auto) maxNorm( const DenseMatrix<MT,SO>& dm )
826 {
827 BLAZE_FUNCTION_TRACE;
828
829 return linfNorm( *dm );
830 }
831 //*************************************************************************************************
832
833 } // namespace blaze
834
835 #endif
836