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