From 8531953d8d7817be65b7c1f964d38f137b033a20 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 2 May 2019 13:27:07 -0500 Subject: [PATCH 01/14] Adding n-dimensional dynamic array type --- .clang-format | 2 +- blaze_tensor/math/Array.h | 157 + blaze_tensor/math/DenseArray.h | 137 + blaze_tensor/math/DenseTensor.h | 84 +- blaze_tensor/math/DynamicArray.h | 205 + blaze_tensor/math/InitFromValue.h | 59 + blaze_tensor/math/InitializerList.h | 353 +- blaze_tensor/math/ReductionFlag.h | 16 + blaze_tensor/math/constraints/Array.h | 88 + blaze_tensor/math/constraints/DenseArray.h | 87 + blaze_tensor/math/dense/DenseArray.h | 557 +++ blaze_tensor/math/dense/DynamicArray.h | 3543 +++++++++++++++++ blaze_tensor/math/dense/DynamicTensor.h | 2 +- blaze_tensor/math/expressions/ArrArrMapExpr.h | 74 + blaze_tensor/math/expressions/ArrMapExpr.h | 74 + blaze_tensor/math/expressions/ArrReduceExpr.h | 75 + .../math/expressions/ArrScalarDivExpr.h | 74 + .../math/expressions/ArrScalarMultExpr.h | 75 + blaze_tensor/math/expressions/Array.h | 1740 ++++++++ .../math/expressions/DArrDArrMapExpr.h | 1259 ++++++ blaze_tensor/math/expressions/DArrMapExpr.h | 2433 +++++++++++ blaze_tensor/math/expressions/DArrNormExpr.h | 435 ++ .../math/expressions/DArrReduceExpr.h | 1371 +++++++ .../math/expressions/DArrScalarDivExpr.h | 1170 ++++++ .../math/expressions/DArrScalarMultExpr.h | 1418 +++++++ blaze_tensor/math/expressions/DenseArray.h | 250 ++ blaze_tensor/math/expressions/Forward.h | 16 +- blaze_tensor/math/smp/ArrayThreadMapping.h | 113 + blaze_tensor/math/smp/DenseArray.h | 57 + blaze_tensor/math/smp/default/DenseArray.h | 257 ++ blaze_tensor/math/smp/hpx/DenseArray.h | 568 +++ blaze_tensor/math/typetraits/IsArray.h | 129 + blaze_tensor/math/typetraits/IsDenseArray.h | 131 + .../math/typetraits/IsRowMajorArray.h | 138 + blaze_tensor/util/ArrayForEach.h | 455 +++ .../mathtest/densearray/GeneralTest.h | 385 ++ blazetest/src/mathtest/CMakeLists.txt | 1 + .../src/mathtest/densearray/CMakeLists.txt | 44 + .../src/mathtest/densearray/GeneralTest.cpp | 3143 +++++++++++++++ 39 files changed, 21164 insertions(+), 11 deletions(-) create mode 100644 blaze_tensor/math/Array.h create mode 100644 blaze_tensor/math/DenseArray.h create mode 100644 blaze_tensor/math/DynamicArray.h create mode 100644 blaze_tensor/math/InitFromValue.h create mode 100644 blaze_tensor/math/constraints/Array.h create mode 100644 blaze_tensor/math/constraints/DenseArray.h create mode 100644 blaze_tensor/math/dense/DenseArray.h create mode 100644 blaze_tensor/math/dense/DynamicArray.h create mode 100644 blaze_tensor/math/expressions/ArrArrMapExpr.h create mode 100644 blaze_tensor/math/expressions/ArrMapExpr.h create mode 100644 blaze_tensor/math/expressions/ArrReduceExpr.h create mode 100644 blaze_tensor/math/expressions/ArrScalarDivExpr.h create mode 100644 blaze_tensor/math/expressions/ArrScalarMultExpr.h create mode 100644 blaze_tensor/math/expressions/Array.h create mode 100644 blaze_tensor/math/expressions/DArrDArrMapExpr.h create mode 100644 blaze_tensor/math/expressions/DArrMapExpr.h create mode 100644 blaze_tensor/math/expressions/DArrNormExpr.h create mode 100644 blaze_tensor/math/expressions/DArrReduceExpr.h create mode 100644 blaze_tensor/math/expressions/DArrScalarDivExpr.h create mode 100644 blaze_tensor/math/expressions/DArrScalarMultExpr.h create mode 100644 blaze_tensor/math/expressions/DenseArray.h create mode 100644 blaze_tensor/math/smp/ArrayThreadMapping.h create mode 100644 blaze_tensor/math/smp/DenseArray.h create mode 100644 blaze_tensor/math/smp/default/DenseArray.h create mode 100644 blaze_tensor/math/smp/hpx/DenseArray.h create mode 100644 blaze_tensor/math/typetraits/IsArray.h create mode 100644 blaze_tensor/math/typetraits/IsDenseArray.h create mode 100644 blaze_tensor/math/typetraits/IsRowMajorArray.h create mode 100644 blaze_tensor/util/ArrayForEach.h create mode 100644 blazetest/blazetest/mathtest/densearray/GeneralTest.h create mode 100644 blazetest/src/mathtest/densearray/CMakeLists.txt create mode 100644 blazetest/src/mathtest/densearray/GeneralTest.cpp diff --git a/.clang-format b/.clang-format index 62ea026..06af678 100644 --- a/.clang-format +++ b/.clang-format @@ -44,7 +44,7 @@ BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: true - AfterControlStatement: true + AfterControlStatement: false AfterEnum: true AfterFunction: true AfterNamespace: false diff --git a/blaze_tensor/math/Array.h b/blaze_tensor/math/Array.h new file mode 100644 index 0000000..15937b4 --- /dev/null +++ b/blaze_tensor/math/Array.h @@ -0,0 +1,157 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/Array.h +// \brief Header file for all basic Array functionality +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_ARRAY_H_ +#define _BLAZE_TENSOR_MATH_ARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + +#include + +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Array functions */ +//@{ +template< typename MT > +bool isUniform( const Array& m ); +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checks if the given tensor is a uniform tensor. +// \ingroup tensor +// +// \param m The tensor to be checked. +// \return \a true if the tensor is a uniform tensor, \a false if not. +// +// This function checks if the given dense or sparse tensor is a uniform tensor. The tensor +// is considered to be uniform if all its elements are identical. The following code example +// demonstrates the use of the function: + + \code + blaze::Dynamictensor A, B; + // ... Initialization + if( isUniform( A ) ) { ... } + \endcode + +// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed +// semantics (blaze::relaxed): + + \code + if( isUniform( A ) ) { ... } + \endcode + +// It is also possible to check if a tensor expression results in a uniform tensor: + + \code + if( isUniform( A * B ) ) { ... } + \endcode + +// However, note that this might require the complete evaluation of the expression, including +// the generation of a temporary tensor. +*/ +template< typename MT > // Type of the tensor +inline bool isUniform( const Array& t ) +{ + return isUniform( ~t ); +} +//************************************************************************************************* + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Array operators */ +//@{ +template< typename MT > +inline std::ostream& operator<<( std::ostream& os, const Array& m ); +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Global output operator for dense and sparse tensors. +// \ingroup tensor +// +// \param os Reference to the output stream. +// \param m Reference to a constant tensor object. +// \return Reference to the output stream. +*/ +template< typename MT > +inline std::ostream& operator<<( std::ostream& os, const Array& m ) +{ + CompositeType_t tmp( ~m ); + +// for (size_t k = 0UL; k < tmp.pages(); ++k) { +// os << "("; +// for (size_t i = 0UL; i < tmp.rows(); ++i) { +// os << "("; +// for (size_t j = 0UL; j < tmp.columns(); ++j) { +// os << std::setw(12) << tmp(k, i, j) << " "; +// } +// os << ") "; +// } +// os << ")\n"; +// } + + return os; +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/DenseArray.h b/blaze_tensor/math/DenseArray.h new file mode 100644 index 0000000..3147fc6 --- /dev/null +++ b/blaze_tensor/math/DenseArray.h @@ -0,0 +1,137 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/DenseArray.h +// \brief Header file for all basic DenseArray functionality +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +// #include +// #include +#include +// #include +// #include +// #include +// #include +#include +#include +#include +#include +#include +// #include +#include +#include + +#endif diff --git a/blaze_tensor/math/DenseTensor.h b/blaze_tensor/math/DenseTensor.h index 9e156f1..192069f 100644 --- a/blaze_tensor/math/DenseTensor.h +++ b/blaze_tensor/math/DenseTensor.h @@ -1,7 +1,7 @@ //================================================================================================= /*! -// \file blaze_tensor/math/DenseMatrix.h -// \brief Header file for all basic DenseMatrix functionality +// \file blaze_tensor/math/DenseTensor.h +// \brief Header file for all basic DenseTensor functionality // // Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved // Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved @@ -41,7 +41,85 @@ // Includes //************************************************************************************************* -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/blaze_tensor/math/DynamicArray.h b/blaze_tensor/math/DynamicArray.h new file mode 100644 index 0000000..417d10d --- /dev/null +++ b/blaze_tensor/math/DynamicArray.h @@ -0,0 +1,205 @@ +//================================================================================================= +/*! +// \file blaze_array/math/DynamicArray.h +// \brief Header file for the complete DynamicArray implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_DYNAMICARRAY_H_ +#define _BLAZE_TENSOR_MATH_DYNAMICARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// RAND SPECIALIZATION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the Rand class template for DynamicArray. +// \ingroup random +// +// This specialization of the Rand class creates random instances of DynamicArray. +*/ +template< size_t N, typename Type > // Data type of the array +class Rand< DynamicArray > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + template< typename... Dims > + inline const DynamicArray generate( Dims... dims ) const; + + template< typename Arg, typename... Dims > + inline const DynamicArray generate( const Arg& min, const Arg& max, Dims... dims ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( DynamicArray& array ) const; + + template< typename Arg > + inline void randomize( DynamicArray& array, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Generation of a random DynamicArray. +// +// \param m The number of rows of the random array. +// \param n The number of columns of the random array. +// \return The generated random array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline const DynamicArray + Rand< DynamicArray >::generate( Dims... dims ) const +{ + DynamicArray array( dims... ); + randomize( array ); + return array; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Generation of a random DynamicArray. +// +// \param m The number of rows of the random array. +// \param n The number of columns of the random array. +// \param min The smallest possible value for a array element. +// \param max The largest possible value for a array element. +// \return The generated random array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename Arg, typename... Dims > // Min/max argument type +inline const DynamicArray + Rand< DynamicArray >::generate( const Arg& min, const Arg& max, Dims... dims ) const +{ + DynamicArray array( dims... ); + randomize( array, min, max ); + return array; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a DynamicArray. +// +// \param array The array to be randomized. +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void Rand< DynamicArray >::randomize( DynamicArray& array ) const +{ + using blaze::randomize; + + ArrayForEach( array.dimensions(), + [v = array.data()]( size_t i ) { randomize( v[i] ); } ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a DynamicArray. +// +// \param array The array to be randomized. +// \param min The smallest possible value for a array element. +// \param max The largest possible value for a array element. +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename Arg > // Min/max argument type +inline void Rand< DynamicArray< N, Type > >::randomize( + DynamicArray< N, Type >& array, const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + ArrayForEach( array.dimensions(), [v = array.data(), min, max]( size_t i ) { + randomize( v[i], min, max ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MAKE FUNCTIONS +// +//================================================================================================= + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/InitFromValue.h b/blaze_tensor/math/InitFromValue.h new file mode 100644 index 0000000..788cc14 --- /dev/null +++ b/blaze_tensor/math/InitFromValue.h @@ -0,0 +1,59 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/InitFromValue.h +// \brief Header file for the init_from_value functionality +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_TENSOR_MATH_INITFROMVALUE_H_ +#define _BLAZE_TENSOR_TENSOR_MATH_INITFROMVALUE_H_ + + +namespace blaze { + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Defines a tag type to be used to initialize arrays from a value. +// \ingroup math +*/ +struct InitFromValue {}; + +constexpr InitFromValue init_from_value{}; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/InitializerList.h b/blaze_tensor/math/InitializerList.h index 9aeb085..99aa0a0 100644 --- a/blaze_tensor/math/InitializerList.h +++ b/blaze_tensor/math/InitializerList.h @@ -59,7 +59,9 @@ namespace blaze { // \return The number of non-zeros elements. */ template< typename Type > -inline size_t nonZeros( initializer_list< initializer_list< initializer_list > > list ) noexcept +inline constexpr size_t nonZeros( + initializer_list< initializer_list< initializer_list< Type > > > + list ) noexcept { size_t nonzeros( 0UL ); @@ -74,6 +76,177 @@ inline size_t nonZeros( initializer_list< initializer_list< initializer_list +inline constexpr size_t determineCubes( initializer_list< initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > > + list ) noexcept +{ + size_t cubes( 0UL ); + for( const auto& cube : list ) { + cubes = max( cubes, cube.size() ); + } + return cubes; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Determines the maximum number of pages specified by the given initializer list. +// \ingroup math +// +// \param list The given initializer list +// \return The maximum number of pages. +*/ +template< typename Type > +inline constexpr size_t determinePages( initializer_list< initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > > + list ) noexcept +{ + size_t pages( 0UL ); + + for( const auto& cube : list ) { + for( const auto& page_list : cube ) { + pages = max( pages, page_list.size() ); + } + } + return pages; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Determines the maximum number of rows specified by the given initializer list. +// \ingroup math +// +// \param list The given initializer list +// \return The maximum number of rows. +*/ +template< typename Type > +inline constexpr size_t determineRows( initializer_list< initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > > + list ) noexcept +{ + size_t rows( 0UL ); + + for( const auto& cube : list ) { + for( const auto& page_list : list ) { + for( const auto& row_list : page_list ) { + rows = max( rows, row_list.size() ); + } + } + } + return rows; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Determines the maximum number of columns specified by the given initializer list. +// \ingroup math +// +// \param list The given initializer list +// \return The maximum number of columns. +*/ +template< typename Type > +inline constexpr size_t determineColumns( initializer_list< initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > > + list ) noexcept +{ + size_t cols( 0UL ); + + for( const auto& cube : list ) { + for( const auto& page_list : list ) { + for( const auto& row_list : page_list ) { + for(const auto& col_list : row_list) { + cols = max( cols, col_list.size() ); + } + } + } + } + return cols; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Determines the maximum number of pages specified by the given initializer list. +// \ingroup math +// +// \param list The given initializer list +// \return The maximum number of pages. +*/ +template< typename Type > +inline constexpr size_t determinePages( initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > + list ) noexcept +{ + size_t pages( 0UL ); + + for( const auto& cube : list ) { + pages = max( pages, cube.size() ); + } + return pages; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Determines the maximum number of columns specified by the given initializer list. +// \ingroup math +// +// \param list The given initializer list +// \return The maximum number of columns. +*/ +template< typename Type > +inline constexpr size_t determineColumns( initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > + list ) noexcept +{ + size_t cols( 0UL ); + + for( const auto& cube : list ) { + for( const auto& page_list : list ) { + for( const auto& row_list : page_list ) { + cols = max( cols, row_list.size() ); + } + } + } + return cols; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Determines the maximum number of rows specified by the given initializer list. +// \ingroup math +// +// \param list The given initializer list +// \return The maximum number of rows. +*/ +template< typename Type > +inline constexpr size_t determineRows( initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > + list ) noexcept +{ + size_t rows( 0UL ); + + for( const auto& cube : list ) { + for( const auto& page_list : cube ) { + rows = max( rows, page_list.size() ); + } + } + return rows; +} +//************************************************************************************************* + + //************************************************************************************************* /*!\brief Determines the maximum number of columns specified by the given initializer list. // \ingroup math @@ -82,7 +255,9 @@ inline size_t nonZeros( initializer_list< initializer_list< initializer_list -inline size_t determineColumns( initializer_list< initializer_list< initializer_list > > list ) noexcept +inline constexpr size_t determineColumns( + initializer_list< initializer_list< initializer_list< Type > > > + list ) noexcept { size_t cols( 0UL ); @@ -103,7 +278,9 @@ inline size_t determineColumns( initializer_list< initializer_list< initializer_ // \return The maximum number of rows. */ template< typename Type > -inline size_t determineRows( initializer_list< initializer_list< initializer_list > > list ) noexcept +inline constexpr size_t determineRows( + initializer_list< initializer_list< initializer_list< Type > > > + list ) noexcept { size_t rows( 0UL ); @@ -114,6 +291,176 @@ inline size_t determineRows( initializer_list< initializer_list< initializer_lis } //************************************************************************************************* +//************************************************************************************************* +/*!\brief Define a nested initializer list type of given dimensionality. +// \ingroup math +*/ +template< size_t N, typename Type > +struct nested_initializer_list; + +template< typename Type > +struct nested_initializer_list< 1, Type > : initializer_list< Type > +{ + using type = initializer_list< Type >; + + constexpr nested_initializer_list(type rhs) : type(std::move(rhs)) {} + + constexpr std::array< size_t, 1 > dimensions() const + { + std::array< size_t, 1 > dims { + this->type::size() + }; + return dims; + } + + template< typename C > + void transfer_data( C& rhs ) + { + std::fill( + std::copy( this->type::begin(), this->type::end(), ( ~rhs ).begin() ), + ( ~rhs ).end(), + Type() ); + } +}; + +template< typename Type > +struct nested_initializer_list< 2, Type > + : initializer_list< initializer_list< Type > > +{ + using type = initializer_list< initializer_list< Type > >; + + constexpr nested_initializer_list(type rhs) : type(std::move(rhs)) {} + + constexpr std::array< size_t, 2 > dimensions() const + { + std::array< size_t, 2 > dims { + determineColumns( *this ), + this->type::size() + }; + return dims; + } + + + template< typename C > + void transfer_data( C& rhs ) + { + size_t i( 0UL ); + for( const auto& rowList : *this ) { + std::fill( + std::copy( rowList.begin(), rowList.end(), ( ~rhs ).begin( i ) ), + ( ~rhs ).end( i ), + Type() ); + ++i; + } + } +}; + +template< typename Type > +struct nested_initializer_list< 3, Type > + : initializer_list< initializer_list< initializer_list< Type > > > +{ + using type = + initializer_list< initializer_list< initializer_list< Type > > >; + + constexpr nested_initializer_list(type rhs) : type(std::move(rhs)) {} + + constexpr std::array< size_t, 3 > dimensions() const + { + std::array< size_t, 3 > dims = { + determineColumns( *this ), + determineRows( *this ), + this->type::size() + }; + return dims; + } + + template< typename C > + void transfer_data( C& rhs ) + { + size_t k( 0UL ); + for (const auto& page : *this) { + size_t i( 0UL ); + for (const auto& rowList : page) { + std::fill( + std::copy( + rowList.begin(), rowList.end(), ( ~rhs ).begin( i, k ) ), + ( ~rhs ).end( i, k ), + Type() ); + ++i; + } + ++k; + } + } +}; + +template< typename Type > +struct nested_initializer_list< 4, Type > + : initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > +{ + using type = initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > >; + + constexpr nested_initializer_list(type rhs) : type(std::move(rhs)) {} + + constexpr std::array< size_t, 4 > dimensions() const + { + std::array< size_t, 4 > dims = { + determineColumns( *this ), + determineRows( *this ), + determinePages( *this ), + this->type::size() + }; + return dims; + } + + template< typename C > + void transfer_data( C& rhs ) + { + size_t l( 0UL ); + for( const auto& cube : *this ) { + size_t k( 0UL ); + for( const auto& page_list : cube ) { + size_t i( 0UL ); + for( const auto& row_list : page_list ) { + std::fill( std::copy( row_list.begin(), + row_list.end(), + ( ~rhs ).begin( i, l, k ) ), + ( ~rhs ).end( i, l, k ), + Type() ); + ++i; + } + ++k; + } + ++l; + } + } +}; + +template< typename Type > +struct nested_initializer_list< 5, Type > + : initializer_list< initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > > +{ + using type = initializer_list< initializer_list< + initializer_list< initializer_list< initializer_list< Type > > > > >; + + constexpr nested_initializer_list(type rhs) : type(std::move(rhs)) {} + + constexpr std::array< size_t, 5 > dimensions() const + { + std::array< size_t, 5 > dims = { + determineColumns( *this ), + determineRows( *this ), + determinePages( *this ), + determineCubes( *this ), + this->type::size() + }; + return dims; + } +}; +//************************************************************************************************* + } // namespace blaze #endif diff --git a/blaze_tensor/math/ReductionFlag.h b/blaze_tensor/math/ReductionFlag.h index d52f1eb..5b37e96 100644 --- a/blaze_tensor/math/ReductionFlag.h +++ b/blaze_tensor/math/ReductionFlag.h @@ -71,6 +71,22 @@ namespace blaze { constexpr size_t pagewise = 2UL; //************************************************************************************************* +//************************************************************************************************* +/*!\brief Reduction flag for arbitrary reduction operations. +// +// This flag can be used to perform arbitrary reduction operations on arrays. The following +// example shows the row-wise summation of a tensor: + + \code + blaze::DynamicArray<3, int> A{ { { 4, 1, 2 }, { -2, 0, 3 } }, { { 4, 1, 2 }, { -2, 0, 3 } } }; + + auto m = sum>( A ); // Results in { { 8, 2, 4 }, { -4, 0, 6 } } + \endcode +*/ +template< size_t N > +constexpr size_t reduction = N; +//************************************************************************************************* + } // namespace blaze #endif diff --git a/blaze_tensor/math/constraints/Array.h b/blaze_tensor/math/constraints/Array.h new file mode 100644 index 0000000..de9ca77 --- /dev/null +++ b/blaze_tensor/math/constraints/Array.h @@ -0,0 +1,88 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/constraints/Array.h +// \brief Constraint on the data type +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_CONSTRAINTS_ARRAY_H_ +#define _BLAZE_TENSOR_MATH_CONSTRAINTS_ARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// MUST_BE_ARRAY_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is not a N-dimensional array type, a compilation error +// is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_ARRAY_TYPE(T) \ + static_assert( ::blaze::IsArray_v, "Non-array type detected" ) +//************************************************************************************************* + + + + +//================================================================================================= +// +// MUST_NOT_BE_ARRAY_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is a N-dimensional array type, a compilation error +// is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_ARRAY_TYPE(T) \ + static_assert( !::blaze::IsArray_v, "Array type detected" ) +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/constraints/DenseArray.h b/blaze_tensor/math/constraints/DenseArray.h new file mode 100644 index 0000000..5f509a4 --- /dev/null +++ b/blaze_tensor/math/constraints/DenseArray.h @@ -0,0 +1,87 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/constraints/DenseArray.h +// \brief Constraint on the data type +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_CONSTRAINTS_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_CONSTRAINTS_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + +namespace blaze { + +//================================================================================================= +// +// MUST_BE_DENSE_ARRAY_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is not a dense, N-dimensional array type, a compilation +// error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE(T) \ + static_assert( ::blaze::IsDenseArray_v, "Non-dense array type detected" ) +//************************************************************************************************* + + + + +//================================================================================================= +// +// MUST_NOT_BE_DENSE_ARRAY_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is a dense, N-dimensional array type, a compilation +// error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_DENSE_ARRAY_TYPE(T) \ + static_assert( !::blaze::IsDenseArray_v, "Dense array type detected" ) +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/dense/DenseArray.h b/blaze_tensor/math/dense/DenseArray.h new file mode 100644 index 0000000..cb34e11 --- /dev/null +++ b/blaze_tensor/math/dense/DenseArray.h @@ -0,0 +1,557 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/dense/DenseArray.h +// \brief Header file for utility functions for dense arrays +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_DENSE_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_DENSE_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include +// #include +#include +// #include +// #include +// #include +// #include +#include +#include +#include +#include +#include +// #include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseArray operators */ +//@{ +template< typename T1, typename T2 > +inline auto operator==( const DenseArray& arr, T2 scalar ) + -> EnableIf_t< IsNumeric_v, bool >; + +template< typename T1, typename T2 > +inline auto operator==( T1 scalar, const DenseArray& arr ) + -> EnableIf_t< IsNumeric_v, bool >; + +template< typename T1, typename T2 > +inline auto operator!=( const DenseArray& arr, T2 scalar ) + -> EnableIf_t< IsNumeric_v, bool >; + +template< typename T1, typename T2 > +inline auto operator!=( T1 scalar, const DenseArray& arr ) + -> EnableIf_t< IsNumeric_v, bool >; + +template< typename TT, typename ST > +inline auto operator*=( DenseArray& arr, ST scalar ) + -> EnableIf_t< IsNumeric_v, TT& >; + +template< typename TT, typename ST > +inline auto operator/=( DenseArray& arr, ST scalar ) + -> EnableIf_t< IsNumeric_v, TT& >; +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Equality operator for the comparison of a row-major dense array and a scalar value. +// \ingroup dense_tensor +// +// \param arr The left-hand side row-major dense array for the comparison. +// \param scalar The right-hand side scalar value for the comparison. +// \return \a true if all elements of the array are equal to the scalar, \a false if not. +// +// If all values of the array are equal to the scalar value, the equality test returns \a true, +// otherwise \a false. Note that this function can only be used with built-in, numerical data +// types! +*/ +template< typename T1 // Type of the left-hand side dense array + , typename T2 > // Type of the right-hand side scalar +inline auto operator==( const DenseArray& arr, T2 scalar ) + -> EnableIf_t< IsNumeric_v, bool > +{ + using CT1 = CompositeType_t; + + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); + + // Evaluation of the dense array operand + CT1 A( ~arr ); + + // In order to compare the array and the scalar value, the data values of the lower-order + // data type are converted to the higher-order data type within the equal function. + return ArrayForEachGroupedAllOf( + ( ~arr ).dimensions(), [&]( std::array< size_t, N > const& dims ) { + return equal( A( dims ), scalar ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Equality operator for the comparison of a scalar value and a dense array. +// \ingroup dense_tensor +// +// \param scalar The left-hand side scalar value for the comparison. +// \param arr The right-hand side dense array for the comparison. +// \return \a true if all elements of the array are equal to the scalar, \a false if not. +// +// If all values of the array are equal to the scalar value, the equality test returns \a true, +// otherwise \a false. Note that this function can only be used with built-in, numerical data +// types! +*/ +template< typename T1 // Type of the left-hand side scalar + , typename T2 > // Type of the right-hand side dense array +inline auto operator==( T1 scalar, const DenseArray& arr ) + -> EnableIf_t< IsNumeric_v, bool > +{ + return ( arr == scalar ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Inequality operator for the comparison of a dense array and a scalar value. +// \ingroup dense_tensor +// +// \param arr The left-hand side dense array for the comparison. +// \param scalar The right-hand side scalar value for the comparison. +// \return \a true if at least one element of the array is different from the scalar, \a false if not. +// +// If one value of the array is inequal to the scalar value, the inequality test returns \a true, +// otherwise \a false. Note that this function can only be used with built-in, numerical data +// types! +*/ +template< typename T1 // Type of the left-hand side scalar + , typename T2 > // Type of the right-hand side dense array +inline auto operator!=( const DenseArray& arr, T2 scalar ) + -> EnableIf_t< IsNumeric_v, bool > +{ + return !( arr == scalar ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Inequality operator for the comparison of a scalar value and a dense array. +// \ingroup dense_tensor +// +// \param scalar The left-hand side scalar value for the comparison. +// \param arr The right-hand side dense array for the comparison. +// \return \a true if at least one element of the array is different from the scalar, \a false if not. +// +// If one value of the array is inequal to the scalar value, the inequality test returns \a true, +// otherwise \a false. Note that this function can only be used with built-in, numerical data +// types! +*/ +template< typename T1 // Type of the left-hand side scalar + , typename T2 > // Type of the right-hand side dense array +inline auto operator!=( T1 scalar, const DenseArray& arr ) + -> EnableIf_t< IsNumeric_v, bool > +{ + return !( arr == scalar ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Multiplication assignment operator for the multiplication of a dense array and +// a scalar value (\f$ A*=s \f$). +// \ingroup dense_tensor +// +// \param arr The left-hand side dense array for the multiplication. +// \param scalar The right-hand side scalar value for the multiplication. +// \return Reference to the left-hand side dense array. +// \exception std::invalid_argument Invalid scaling of restricted array. +// +// In case the array \a TT is restricted and the assignment would violate an invariant of the +// array, a \a std::invalid_argument exception is thrown. +*/ +template< typename TT // Type of the left-hand side dense array + , typename ST > // Data type of the right-hand side scalar +inline auto operator*=( DenseArray& arr, ST scalar ) + -> EnableIf_t< IsNumeric_v, TT& > +{ + if( IsRestricted_v ) { + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~arr ) > >::num_dimensions(); + + std::array< size_t, N > dims{}; + if( !tryMult( ~arr, dims, (~arr).dimensions(), scalar ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted array" ); + } + } + + BLAZE_DECLTYPE_AUTO( left, derestrict( ~arr ) ); + + smpAssign( left, left * scalar ); + + BLAZE_INTERNAL_ASSERT( isIntact( ~arr ), "Invariant violation detected" ); + + return ~arr; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Multiplication assignment operator for the multiplication of a temporary dense array +// and a scalar value (\f$ A*=s \f$). +// \ingroup dense_tensor +// +// \param arr The left-hand side temporary dense array for the multiplication. +// \param scalar The right-hand side scalar value for the multiplication. +// \return Reference to the left-hand side dense array. +// \exception std::invalid_argument Invalid scaling of restricted array. +// +// In case the array \a TT is restricted and the assignment would violate an invariant of the +// array, a \a std::invalid_argument exception is thrown. +*/ +template< typename TT // Type of the left-hand side dense array + , typename ST > // Data type of the right-hand side scalar +inline auto operator*=( DenseArray&& arr, ST scalar ) + -> EnableIf_t< IsNumeric_v, TT& > +{ + return operator*=( ~arr, scalar ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Division assignment operator for the division of a dense array by a scalar value +// (\f$ A/=s \f$). +// \ingroup dense_tensor +// +// \param arr The left-hand side dense array for the division. +// \param scalar The right-hand side scalar value for the division. +// \return Reference to the left-hand side dense array. +// \exception std::invalid_argument Invalid scaling of restricted array. +// +// In case the array \a TT is restricted and the assignment would violate an invariant of the +// array, a \a std::invalid_argument exception is thrown. +// +// \note A division by zero is only checked by an user assert. +*/ +template< typename TT // Type of the left-hand side dense array + , typename ST > // Data type of the right-hand side scalar +inline auto operator/=( DenseArray& arr, ST scalar ) + -> EnableIf_t< IsNumeric_v, TT& > +{ +// BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_TENSOR_TYPE( TT ); + + BLAZE_USER_ASSERT( !isZero( scalar ), "Division by zero detected" ); + + if( IsRestricted_v ) { + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~arr ) > >::num_dimensions(); + + std::array< size_t, N > dims{}; + if( !tryDiv( ~arr, dims, (~arr).dimensions(), scalar ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted array" ); + } + } + + BLAZE_DECLTYPE_AUTO( left, derestrict( ~arr ) ); + + smpAssign( left, left / scalar ); + + BLAZE_INTERNAL_ASSERT( isIntact( ~arr ), "Invariant violation detected" ); + + return ~arr; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Division assignment operator for the division of a temporary dense array by a scalar +// value (\f$ A/=s \f$). +// \ingroup dense_tensor +// +// \param arr The left-hand side temporary dense array for the division. +// \param scalar The right-hand side scalar value for the division. +// \return Reference to the left-hand side dense array. +// \exception std::invalid_argument Invalid scaling of restricted array. +// +// In case the array \a TT is restricted and the assignment would violate an invariant of the +// array, a \a std::invalid_argument exception is thrown. +// +// \note A division by zero is only checked by an user assert. +*/ +template< typename TT // Type of the left-hand side dense array + , typename ST > // Data type of the right-hand side scalar +inline auto operator/=( DenseArray&& arr, ST scalar ) + -> EnableIf_t< IsNumeric_v, TT& > +{ + return operator/=( ~arr, scalar ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseArray functions */ +//@{ +template< typename TT > +bool isnan( const DenseArray& dm ); + +// template< bool RF, typename MT > +// bool isSymmetric( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isHermitian( const DenseArray& dm ); + +template< bool RF, typename MT > +bool isUniform( const DenseArray& dm ); + +// template< bool RF, typename MT > +// bool isLower( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isUniLower( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isStrictlyLower( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isUpper( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isUniUpper( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isStrictlyUpper( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isDiagonal( const DenseArray& dm ); +// +// template< bool RF, typename MT > +// bool isIdentity( const DenseArray& dm ); + +template< typename MT > +auto softmax( const DenseArray& dm ); +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checks the given dense array for not-a-number elements. +// \ingroup dense_tensor +// +// \param dm The array to be checked for not-a-number elements. +// \return \a true if at least one element of the array is not-a-number, \a false otherwise. +// +// This function checks the dense array for not-a-number (NaN) elements. If at least one +// element of the array is not-a-number, the function returns \a true, otherwise it returns +// \a false. + + \code + blaze::DynamicArray A( 5UL, 3UL, 4UL ); + // ... Initialization + if( isnan( A ) ) { ... } + \endcode + +// Note that this function only works for arrays with floating point elements. The attempt to +// use it for a array with a non-floating point element type results in a compile time error. +*/ +template< typename TT > // Type of the dense array +bool isnan( const DenseArray& dm ) +{ + using CT = CompositeType_t; + + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); + + CT A( ~dm ); // Evaluation of the dense array operand + + return ArrayForEachGroupedAnyOf( + ( ~dm ).dimensions(), [&]( std::array< size_t, N > const& dims ) { + return isnan( A( dims ) ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the softmax function for the given dense array. +// \ingroup dense_tensor +// +// \param dm The given dense array for the softmax computation. +// \return The resulting array. +// +// This function computes the softmax function (i.e. the normalized exponential function) for +// the given dense array \a dm (see also https://en.wikipedia.org/wiki/Softmax_function). The +// resulting dense array consists of real values in the range (0..1], which add up to 1. +*/ +template< typename MT > // Type of the dense array +auto softmax( const DenseArray& dm ) +{ + auto tmp( evaluate( exp( ~dm ) ) ); + const auto scalar( sum( ~tmp ) ); + tmp /= scalar; + return tmp; +} +//************************************************************************************************* + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Checks if the given row-major general dense array is a uniform array. +// \ingroup dense_tensor +// +// \param dm The dense array to be checked. +// \return \a true if the array is a uniform array, \a false if not. +*/ +template< bool RF // Relaxation flag + , typename MT > // Type of the dense array +bool isUniform_backend( const DenseArray& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + ArrayDimForEach( ( ~dm ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims_[i] != 0, "Invalid array dimension detected" ); + } ); +#endif + + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); + + std::array< size_t, N > dims{}; + const auto& cmp( (~dm)( dims ) ); + + return ArrayForEachGroupedAllOf( ( ~dm ).dimensions(), + [&]( std::array< size_t, N > const& dims ) { + return equal< RF >( ( ~dm )( dims ), cmp ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checks if the given dense array is a uniform array. +// \ingroup dense_tensor +// +// \param dm The dense array to be checked. +// \return \a true if the array is a uniform array, \a false if not. +// +// This function checks if the given dense array is a uniform array. The array is considered +// to be uniform if all its elements are identical. The following code example demonstrates the +// use of the function: + + \code + blaze::DynamicArray A, B; + // ... Initialization + if( isUniform( A ) ) { ... } + \endcode + +// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed +// semantics (blaze::relaxed): + + \code + if( isUniform( A ) ) { ... } + \endcode + +// It is also possible to check if a array expression results is a uniform array: + + \code + if( isUniform( A * B ) ) { ... } + \endcode + +// However, note that this might require the complete evaluation of the expression, including +// the generation of a temporary array. +*/ +template< bool RF // Relaxation flag + , typename MT > // Type of the dense array +bool isUniform( const DenseArray& dm ) +{ + if( IsUniform_v< MT > || + ArrayDimAnyOf( + ( ~dm ).dimensions(), []( size_t i ) { return i == 0; } ) || + ArrayDimAllOf( + ( ~dm ).dimensions(), []( size_t i ) { return i == 1; } ) ) { + return true; + } + + if( IsUniTriangular_v ) + return false; + + CompositeType_t A( ~dm ); // Evaluation of the dense array operand + + return isUniform_backend( A ); +} +//************************************************************************************************* + + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h new file mode 100644 index 0000000..03a7590 --- /dev/null +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -0,0 +1,3543 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/dense/DynamicArray.h +// \brief Header file for the implementation of a dynamic LxOxMxN array +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_DENSE_DYNAMIC_ARRAY_H_ +#define _BLAZE_TENSOR_MATH_DENSE_DYNAMIC_ARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\defgroup dynamic_array DynamicArray +// \ingroup dense_array +*/ +/*!\brief Efficient implementation of a dynamic \f$ M \times N \f$ array. +// \ingroup dynamic_array +// +// The DynamicArray class template is the representation of an arbitrary sized array with +// \f$ M \times N \f$ dynamically allocated elements of arbitrary type. The type of the elements +// and the storage order of the array can be specified via the two template parameters: + + \code + template< typename Type > + class DynamicArray; + \endcode + +// - Type: specifies the type of the array elements. DynamicArray can be used with any +// non-cv-qualified, non-reference, non-pointer element type. +// +// The use of DynamicArray is very natural and intuitive. All operations (addition, subtraction, +// multiplication, scaling, ...) can be performed on all possible combinations of matrices with +// fitting element types. The following example an impression of the use of DynamicArray: + + \code + using blaze::DynamicArray; + using blaze::CompressedArray; + + DynamicArray<4, double> A( 2, 3, 4, 5 ); // Default constructed, non-initialized, 2x3x4x5 array + A(0,0,0,0) = 1.0; A(0,0,0,1) = 2.0; A(0,0,0,2) = 3.0; // Initialization of the first row + A(0,0,1,0) = 4.0; A(0,0,1,1) = 5.0; A(0,0,1,2) = 6.0; // Initialization of the second row + + DynamicArray<2, float> B( 2, 3 ); // Default constructed column-major single precision 2x3 array + B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row + B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row + + CompressedArray C( 2, 3 ); // Empty sparse single precision array + DynamicArray<2, float> D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 array + + DynamicArray<2, double> E( A ); // Creation of a new array as a copy of A + DynamicArray<2, double> F; // Creation of a default column-major array + + E = A + B; // Array addition and assignment to a array + F = A - C; // Array subtraction and assignment to a column-major array + F = A * D; // Array multiplication between two matrices of different element types + + A *= 2.0; // In-place scaling of array A + E = 2.0 * B; // Scaling of array B + F = D * 2.0; // Scaling of array D + + E += A - B; // Addition assignment + E -= A + C; // Subtraction assignment + F *= A * D; // Multiplication assignment + \endcode +*/ +template< size_t N, typename Type > // Data type of the array +class DynamicArray + : public DenseArray< DynamicArray > +{ + public: + //**Type definitions**************************************************************************** + using This = DynamicArray; //!< Type of this DynamicArray instance. + using BaseType = DenseArray; //!< Base type of this DynamicArray instance. + using ResultType = This; //!< Result type for expression template evaluations. + using OppositeType = DynamicArray; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = DynamicArray; //!< Transpose type for expression template evaluations. + using ElementType = Type; //!< Type of the array elements. + using SIMDType = SIMDTrait_t; //!< SIMD type of the array elements. + using ReturnType = const Type&; //!< Return type for expression template evaluations. + using CompositeType = const This&; //!< Data type for composite expression templates. + + using Reference = Type&; //!< Reference to a non-constant array value. + using ConstReference = const Type&; //!< Reference to a constant array value. + using Pointer = Type*; //!< Pointer to a non-constant array value. + using ConstPointer = const Type*; //!< Pointer to a constant array value. + + using Iterator = DenseIterator; //!< Iterator over non-constant elements. + using ConstIterator = DenseIterator; //!< Iterator over constant elements. + //********************************************************************************************** + + //**Rebind struct definition******************************************************************** + /*!\brief Rebind mechanism to obtain a DynamicArray with different data/element type. + */ + template< typename NewType > // Data type of the other array + struct Rebind { + using Other = DynamicArray; //!< The type of the other DynamicArray. + }; + //********************************************************************************************** + + //**Resize struct definition******************************************************************** + /*!\brief Resize mechanism to obtain a DynamicArray with different fixed dimensions. + */ +// template< size_t... NewDims > // Dimensions of the other array +// struct Resize { +// BLAZE_STATIC_ASSERT_MSG(N == sizeof...(NewDims), "incompatible dimensionality of other array"); +// using Other = DynamicArray; //!< The type of the other DynamicArray. +// }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation flag for SIMD optimization. + /*! The \a simdEnabled compilation flag indicates whether expressions the array is involved + in can be optimized via SIMD operations. In case the element type of the array is a + vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise + it is set to \a false. */ + static constexpr bool simdEnabled = IsVectorizable_v; + + //! Compilation flag for SMP assignments. + /*! The \a smpAssignable compilation flag indicates whether the array can be used in SMP + (shared memory parallel) assignments (both on the left-hand and right-hand side of the + assignment). */ + static constexpr bool smpAssignable = !IsSMPAssignable_v; + //********************************************************************************************** + + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit inline DynamicArray() noexcept; + template< typename... Dims > + explicit inline DynamicArray( size_t dim0, Dims... dims ); + explicit inline DynamicArray( std::array< size_t, N> const& dims ); + template< typename... Dims > + explicit inline DynamicArray( InitFromValue, const Type& init, Dims... dims ); + explicit inline DynamicArray( nested_initializer_list< N, Type > list ); + + template< typename Other, typename... Dims > + explicit inline DynamicArray( const Other* array, Dims... dims ); + + inline DynamicArray( const DynamicArray& m ); + inline DynamicArray( DynamicArray&& m ) noexcept; + template< typename MT> inline DynamicArray( const Array& m ); + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + inline ~DynamicArray(); + //@} + //********************************************************************************************** + + //**Data access functions*********************************************************************** + /*!\name Data access functions */ + //@{ + template< typename... Dims > + inline Reference operator()( Dims... dims ) noexcept; + template< typename... Dims > + inline ConstReference operator()( Dims... dims ) const noexcept; + inline Reference operator()( std::array< size_t, N > const& indices ) noexcept; + inline ConstReference operator()( std::array< size_t, N > const& indices ) const noexcept; + template< typename... Dims > + inline Reference at( Dims... dims ); + template< typename... Dims > + inline ConstReference at( Dims... dims ) const; + inline Reference at( std::array< size_t, N > const& indices ); + inline ConstReference at( std::array< size_t, N > const& indices ) const; + inline Pointer data () noexcept; + inline ConstPointer data () const noexcept; + template< typename... Dims > + inline Pointer data ( size_t i, Dims... subdims ) noexcept; + template< typename... Dims > + inline ConstPointer data ( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline Iterator begin ( size_t i, Dims... subdims ) noexcept; + template< typename... Dims > + inline ConstIterator begin ( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline ConstIterator cbegin( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline Iterator end ( size_t i, Dims... subdims ) noexcept; + template< typename... Dims > + inline ConstIterator end ( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline ConstIterator cend ( size_t i, Dims... subdims ) const noexcept; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + inline DynamicArray& operator=( const Type& rhs ); + inline DynamicArray& operator=( nested_initializer_list< N, Type > list ); + + inline DynamicArray& operator=( const DynamicArray& rhs ); + inline DynamicArray& operator=( DynamicArray&& rhs ) noexcept; + + template< typename MT > inline DynamicArray& operator= ( const Array& rhs ); + template< typename MT > inline DynamicArray& operator+=( const Array& rhs ); + template< typename MT > inline DynamicArray& operator-=( const Array& rhs ); + template< typename MT > inline DynamicArray& operator%=( const Array& rhs ); + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + inline static constexpr size_t num_dimensions() noexcept { return N; } + inline constexpr std::array< size_t, N > const& dimensions() const noexcept; + template < size_t Dim > + inline size_t dimension() const noexcept; + inline size_t spacing() const noexcept; + inline size_t capacity() const noexcept; + template< typename... Dims > + inline size_t capacity( size_t i, Dims... subdims ) const noexcept; + inline size_t nonZeros() const; + template< typename... Dims > + inline size_t nonZeros( size_t i, Dims... subdims ) const; + inline void reset(); + template< typename... Dims > + inline void reset( size_t i, Dims... subdims ); + inline void clear(); + void resize( std::array< size_t, N > const& dims, bool preserve = true ); + inline void extend( std::array< size_t, N > const& dims, bool preserve = true ); + inline void reserve( size_t elements ); + inline void shrinkToFit(); + inline void swap( DynamicArray& m ) noexcept; + //@} + //********************************************************************************************** + + //**Numeric functions*************************************************************************** + /*!\name Numeric functions */ + //@{ + inline DynamicArray& transpose(); + inline DynamicArray& ctranspose(); + template < typename T > + inline DynamicArray& transpose( const T* indices, size_t n ); + template < typename T > + inline DynamicArray& ctranspose( const T* indices, size_t n ); + + template< typename Other > inline DynamicArray& scale( const Other& scalar ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + IsRowMajorArray_v< MT >); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedAddAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + HasSIMDAdd_v< Type, ElementType_t > && + IsRowMajorArray_v< MT >); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedSubAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + HasSIMDSub_v< Type, ElementType_t > && + IsRowMajorArray_v< MT >); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedSchurAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + HasSIMDMult_v< Type, ElementType_t > && + IsRowMajorArray_v< MT >); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + public: + //**Debugging functions************************************************************************* + /*!\name Debugging functions */ + //@{ + inline bool isIntact() const noexcept; + //@} + //********************************************************************************************** + + //**Expression template evaluation functions**************************************************** + /*!\name Expression template evaluation functions */ + //@{ + template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept; + template< typename Other > inline bool isAliased( const Other* alias ) const noexcept; + + inline bool isAligned () const noexcept; + inline bool canSMPAssign() const noexcept; + + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType load ( Dims... dims ) const noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType loada( Dims... dims ) const noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType loadu( Dims... dims ) const noexcept; + + template< typename... Dims > + BLAZE_ALWAYS_INLINE void store ( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void storea( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void storeu( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void stream( const SIMDType& value, Dims... dims ) noexcept; + + template< typename MT > + inline auto assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v >; + + template< typename MT > + inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; + + template< typename MT > + inline auto addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; + + template< typename MT > + inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; + + template< typename MT > + inline auto subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; + + template< typename MT > + inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; + + template< typename MT > + inline auto schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; + + template< typename MT > + inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; + //@} + //********************************************************************************************** + + private: + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + template< typename... Dims > + inline static std::array< size_t, N > initDimensions( Dims... dims ) noexcept; + inline static std::array< size_t, N > initDimensions( const std::array< size_t, N >& dims ) noexcept; + inline static size_t addPadding( size_t value ) noexcept; + inline size_t calcCapacity() const noexcept; + template< typename... Dims > + inline size_t index( Dims... dims ) const noexcept; + inline size_t index( std::array< size_t, N > const& indices ) const noexcept; + template< typename... Dims > + inline size_t row_index( size_t i, Dims... subdims ) const noexcept; + //@} + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::array< size_t, N > dims_; //!< The current dimensions of the array (dims[1]...dims_[N]) . + size_t nn_; //!< The alignment adjusted number of columns. + size_t capacity_; //!< The maximum capacity of the array. + Type* BLAZE_RESTRICT v_; //!< The dynamically allocated array elements. + //@} + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type ); + BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type ); + BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type ); + BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief The default constructor for DynamicArray. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray::DynamicArray() noexcept + : dims_ ( ) // The current dimensions of the array + , nn_ ( 0UL ) // The length of a padded row + , capacity_( 0UL ) // The maximum capacity of the array + , v_ ( nullptr ) // The array elements +{} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Constructor for a array of size \f$ m \times n \f$. No element initialization is performed! +// +// \param m The number of rows of the array. +// \param n The number of columns of the array. +// +// \note This constructor is only responsible to allocate the required dynamic memory. No +// element initialization is performed! +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline DynamicArray< N, Type >::DynamicArray( size_t dim0, Dims... dims ) + : dims_ ( initDimensions( dim0, dims... ) ) // The current dimensions of the array + , nn_ ( addPadding( dims_[0] ) ) // The length of a padded row + , capacity_( calcCapacity() ) // The maximum capacity of the array + , v_( allocate< Type >( capacity_ ) ) // The array elements +{ + BLAZE_STATIC_ASSERT( N - 1 == sizeof...( dims ) ); + + if( IsVectorizable_v ) { + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { v_[i] = Type(); } ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Constructor for a homogeneous initialization of all \f$ m \times n \f$ array elements. +// +// \param m The number of rows of the array. +// \param n The number of columns of the array. +// \param init The initial value of the array elements. +// +// All array elements are initialized with the specified value. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline DynamicArray::DynamicArray( InitFromValue, const Type& init, Dims...dims ) + : DynamicArray( dims... ) +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + ArrayForEach( dims_, [&]( size_t i ) { v_[i] = init; } ); + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief List initialization of all array elements. +// +// \param list The initializer list. +// +// This constructor provides the option to explicitly initialize the elements of the array by +// means of an initializer list: + + \code + using blaze::rowMajor; + + blaze::DynamicArray A{ { { 1, 2, 3 }, + { 4, 5 }, + { 7, 8, 9 } }, + { { 1, 2, 3 }, + { 4, 5 }, + { 7, 8, 9 } } }; + \endcode + +// The array is sized according to the size of the initializer list and all its elements are +// initialized by the values of the given initializer list. Missing values are initialized as +// default (as e.g. the value 6 in the example). +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray::DynamicArray( nested_initializer_list< N, Type > list ) + : DynamicArray( list.dimensions() ) +{ + list.transfer_data( *this ); + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Array initialization of all array elements. +// +// \param m The number of rows of the array. +// \param n The number of columns of the array. +// \param array Dynamic array for the initialization. +// +// This constructor offers the option to directly initialize the elements of the array with +// a dynamic array: + + \code + using blaze::rowMajor; + + int* array = new int[20]; + // ... Initialization of the dynamic array + blaze::DynamicArray v( 6UL, 4UL, 5UL, array ); + delete[] array; + \endcode + +// The array is sized according to the given size of the array and initialized with the values +// from the given array. Note that it is expected that the given \a array has at least \a m by +// \a n elements. Providing an array with less elements results in undefined behavior! +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename Other, typename... Dims > // Data type of the initialization array +inline DynamicArray::DynamicArray( const Other* array, Dims... dims ) + : DynamicArray( dims... ) +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + ArrayForEach2( dims_, nn_, [&]( size_t i, size_t j ) { v_[i] = array[j]; } ); + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The copy constructor for DynamicArray. +// +// \param m Array to be copied. +// +// The copy constructor is explicitly defined due to the required dynamic memory management +// and in order to enable/facilitate NRV optimization. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray::DynamicArray( const DynamicArray& m ) + : dims_ ( m.dims_ ) // The current dimensions of the array + , nn_ ( m.nn_ ) // The length of a padded row + , capacity_( m.capacity_ ) // The maximum capacity of the array + , v_( allocate< Type >( capacity_ ) ) // The array elements +{ + smpAssign( *this, m ); + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The move constructor for DynamicArray. +// +// \param m The array to be move into this instance. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray::DynamicArray( DynamicArray&& m ) noexcept + : dims_ ( std::move(m.dims_) ) // The current dimensions of the array + , nn_ ( m.nn_ ) // The length of a padded row + , capacity_( m.capacity_ ) // The maximum capacity of the array + , v_ ( m.v_ ) // The array elements +{ + m.nn_ = 0UL; + m.capacity_ = 0UL; + m.v_ = nullptr; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Conversion constructor from different arrays. +// +// \param m Array to be copied. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the foreign array +inline DynamicArray::DynamicArray( const Array& m ) + : DynamicArray( (~m).dimensions() ) +{ + smpAssign( *this, ~m ); + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Constructor from array bounds. +// +// \param m Array to be copied. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray::DynamicArray( const std::array& dims ) + : dims_( initDimensions( dims ) ) // The current dimensions of the array + , nn_ ( addPadding( dims_[0] ) ) // The length of a padded row + , capacity_( calcCapacity() ) // The maximum capacity of the array + , v_( allocate< Type >( capacity_ ) ) // The array elements +{ + if( IsVectorizable_v ) { + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { v_[i] = Type(); } ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + + + +//================================================================================================= +// +// DESTRUCTOR +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief The destructor for DynamicArray. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray::~DynamicArray() +{ + deallocate( v_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// DATA ACCESS FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief ND-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::Reference + DynamicArray::operator()( Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dims_[i], "Invalid array access index" ); + } ); +#endif + + return v_[index( dims... )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ND-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstReference + DynamicArray::operator()( Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dims_[i], "Invalid array access index" ); + } ); +#endif + + return v_[index( dims... )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ND-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline typename DynamicArray::Reference + DynamicArray::operator()( std::array< size_t, N > const& indices ) noexcept +{ +#if defined(BLAZE_USER_ASSERTION) + ArrayDimForEach( dims_, [&]( size_t i ) { + BLAZE_USER_ASSERT( indices[i] < dims_[i], "Invalid array access index" ); + } ); +#endif + + return v_[index( indices )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ND-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline typename DynamicArray::ConstReference + DynamicArray::operator()( std::array< size_t, N > const& indices ) const noexcept +{ +#if defined(BLAZE_USER_ASSERTION) + ArrayDimForEach( dims_, [&]( size_t i ) { + BLAZE_USER_ASSERT( indices[i] < dims_[i], "Invalid array access index" ); + } ); +#endif + + return v_[index( indices )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::Reference + DynamicArray::at( Dims... dims ) +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i ) { + if( indices[N - i - 1] >= dims_[i] ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstReference + DynamicArray::at( Dims... dims ) const +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i ) { + if( indices[N - i - 1] >= dims_[i] ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline typename DynamicArray::Reference + DynamicArray::at( std::array< size_t, N > const& indices ) +{ + ArrayDimForEach( dims_, [&]( size_t i ) { + if( indices[i] >= dims_[i] ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( indices ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline typename DynamicArray::ConstReference + DynamicArray::at( std::array< size_t, N > const& indices ) const +{ + ArrayDimForEach( dims_, [&]( size_t i ) { + if( indices[i] >= dims_[i] ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( indices ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dynamic array. Note that you +// can NOT assume that all array elements lie adjacent to each other! The dynamic array may +// use techniques such as padding to improve the alignment of the data. Whereas the number of +// elements within a row/column are given by the \c rows() and \c columns() member functions, +// respectively, the total number of elements including padding is given by the \c spacing() +// member function. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline typename DynamicArray::Pointer + DynamicArray::data() noexcept +{ + return v_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dynamic array. Note that you +// can NOT assume that all array elements lie adjacent to each other! The dynamic array may +// use techniques such as padding to improve the alignment of the data. Whereas the number of +// elements within a row/column are given by the \c rows() and \c columns() member functions, +// respectively, the total number of elements including padding is given by the \c spacing() +// member function. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline typename DynamicArray::ConstPointer + DynamicArray::data() const noexcept +{ + return v_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage for the elements in row/column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::Pointer + DynamicArray::data( size_t i, Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return v_ + row_index( i, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage for the elements in row/column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstPointer + DynamicArray::data( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return v_ + row_index( i, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the storage order is set to \a rowMajor the function returns an iterator to the first element +// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator +// to the first element of column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::Iterator + DynamicArray::begin( size_t i, Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return Iterator( v_ + row_index( i, dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the storage order is set to \a rowMajor the function returns an iterator to the first element +// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator +// to the first element of column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstIterator + DynamicArray::begin( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the storage order is set to \a rowMajor the function returns an iterator to the first element +// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator +// to the first element of column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstIterator + DynamicArray::cbegin( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the storage order is set to \a rowMajor the function returns an iterator just past +// the last element of row \a i, in case the storage flag is set to \a columnMajor the function +// returns an iterator just past the last element of column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::Iterator + DynamicArray::end( size_t i, Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return Iterator( v_ + row_index( i, dims... ) + dims_[0] ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the storage order is set to \a rowMajor the function returns an iterator just past +// the last element of row \a i, in case the storage flag is set to \a columnMajor the function +// returns an iterator just past the last element of column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstIterator + DynamicArray::end( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( size_t i, dims... ) + dims_[0] ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// +// \param i The row/column index. +// \param j The page index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the storage order is set to \a rowMajor the function returns an iterator just past +// the last element of row \a i, in case the storage flag is set to \a columnMajor the function +// returns an iterator just past the last element of column \a i. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline typename DynamicArray::ConstIterator + DynamicArray::cend( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) + dims_[0] ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ASSIGNMENT OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Homogeneous assignment to all array elements. +// +// \param rhs Scalar value to be assigned to all array elements. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray& DynamicArray::operator=(const Type& rhs) +{ + ArrayForEach( dims_, [&]( size_t i ) { v_[i] = rhs; } ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief List assignment to all array elements. +// +// \param list The initializer list. +// +// This assignment operator offers the option to directly assign to all elements of the array +// by means of an initializer list: + + \code + using blaze::rowMajor; + + blaze::DynamicArray A; + A = { { { 1, 2, 3 }, + { 4, 5 }, + { 7, 8, 9 } } }; + \endcode + +// The array is resized according to the given initializer list and all its elements are +// assigned the values from the given initializer list. Missing values are initialized as +// default (as e.g. the value 6 in the example). +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray& + DynamicArray::operator=( nested_initializer_list< N, Type > list ) +{ + resize( list.dimensions(), false ); + + list.transfer_data( *this ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Copy assignment operator for DynamicArray. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +// +// The array is resized according to the given \f$ M \times N \f$ array and initialized as a +// copy of this array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray& DynamicArray::operator=( const DynamicArray& rhs ) +{ + if( &rhs == this ) return *this; + + resize( rhs.dimensions(), false ); + + smpAssign( *this, ~rhs ); + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Move assignment operator for DynamicArray. +// +// \param rhs The array to be moved into this instance. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray& DynamicArray::operator=( DynamicArray&& rhs ) noexcept +{ + deallocate( v_ ); + + dims_ = std::move( rhs.dims_ ); + nn_ = rhs.nn_; + capacity_ = rhs.capacity_; + v_ = rhs.v_; + + rhs.nn_ = 0UL; + rhs.capacity_ = 0UL; + rhs.v_ = nullptr; + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Assignment operator for different matrices. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +// +// The array is resized according to the given \f$ M \times N \f$ array and initialized as a +// copy of this array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the right-hand side array +inline DynamicArray& DynamicArray::operator=( const Array& rhs ) +{ + if( (~rhs).canAlias( this ) ) { + DynamicArray tmp( ~rhs ); + swap( tmp ); + } + else { + resize( (~rhs).dimensions(), false ); + smpAssign( *this, ~rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Addition assignment operator for the addition of a array (\f$ A+=B \f$). +// +// \param rhs The right-hand side array to be added to the array. +// \return Reference to the array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the right-hand side array +inline DynamicArray& DynamicArray::operator+=( const Array& rhs ) +{ + if( (~rhs).dimensions() != dims_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAddAssign( *this, tmp ); + } + else { + smpAddAssign( *this, ~rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Subtraction assignment operator for the subtraction of a array (\f$ A-=B \f$). +// +// \param rhs The right-hand side array to be subtracted from the array. +// \return Reference to the array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the right-hand side array +inline DynamicArray& DynamicArray::operator-=( const Array& rhs ) +{ + if( (~rhs).dimensions() != dims_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSubAssign( *this, tmp ); + } + else { + smpSubAssign( *this, ~rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Schur product assignment operator for the multiplication of a array (\f$ A\circ=B \f$). +// +// \param rhs The right-hand side array for the Schur product. +// \return Reference to the array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the right-hand side array +inline DynamicArray& DynamicArray::operator%=( const Array& rhs ) +{ + if( (~rhs).dimensions() != dims_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSchurAssign( *this, tmp ); + } + else { + smpSchurAssign( *this, ~rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Returns the current number of elements in the given dimension of the array. +// +// \return The number of cubes of the array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template < size_t Dim > +inline size_t DynamicArray::dimension() const noexcept +{ + BLAZE_STATIC_ASSERT( Dim < N ); + + return dims_[Dim]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the spacing between the beginning of two rows/columns. +// +// \return The spacing between the beginning of two rows/columns. +// +// This function returns the spacing between the beginning of two rows/columns, i.e. the +// total number of elements of a row/column. In case the storage order is set to \a rowMajor +// the function returns the spacing between two rows, in case the storage flag is set to +// \a columnMajor the function returns the spacing between two columns. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray::spacing() const noexcept +{ + return nn_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the maximum capacity of the array. +// +// \return The capacity of the array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray::capacity() const noexcept +{ + return capacity_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the current capacity of the specified row/column. +// +// \param i The index of the row/column. +// \param k The index of the page. +// \return The current capacity of row/column \a i. +// +// This function returns the current capacity of the specified row/column. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline size_t DynamicArray::capacity( size_t i, Dims... dims ) const noexcept +{ + MAYBE_UNUSED( dims... ); + + BLAZE_USER_ASSERT( i < dimension<1>(), "Invalid row access index" ); + + return nn_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the total number of non-zero elements in the array +// +// \return The number of non-zero elements in the dense array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray::nonZeros() const +{ + size_t nonzeros( 0UL ); + + ArrayForEach( dims_, [&]( size_t i ) { + if( !isDefault( v_[i] ) ) { + ++nonzeros; + } + } ); + + return nonzeros; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the number of non-zero elements in the specified row. +// +// \param i The index of the row. +// \return The number of non-zero elements of row \a i. +// +// This function returns the current number of non-zero elements in the specified row. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline size_t DynamicArray::nonZeros( size_t i, Dims... dims ) const +{ + const size_t jstart = row_index( i, dims... ); + const size_t jend = jstart + dims_[0]; + size_t nonzeros( 0UL ); + + for( size_t j = jstart; j < jend; ++j ) + if( !isDefault( v_[j] ) ) + ++nonzeros; + + return nonzeros; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reset to the default initial values. +// +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void DynamicArray::reset() +{ + ArrayForEach( dims_, []( size_t i ) { blaze::clear( v_[i] ); } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reset the specified row/column to the default initial values. +// +// \param i The index of the row/column. +// \return void +// +// This function resets the values in the specified row/column to their default value. In case +// the storage order is set to \a rowMajor the function resets the values in row \a i, in case +// the storage order is set to \a columnMajor the function resets the values in column \a i. +// Note that the capacity of the row/column remains unchanged. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline void DynamicArray::reset( size_t i, Dims... dims ) +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + using blaze::clear; + + BLAZE_USER_ASSERT( i < dimension<1>(), "Invalid row access index" ); + + size_t row_elements = row_index( i, dims... ); + + for( size_t j = 0UL; j < dims_[0]; ++j ) + clear( v_[row_elements + j] ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Clearing the \f$ M \times N \f$ array. +// +// \return void +// +// After the clear() function, the size of the array is 0. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void DynamicArray::clear() +{ + resize( std::array< size_t, N >{}, false ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Changing the size of the array. +// +// \param m The new number of rows of the array. +// \param n The new number of columns of the array. +// \param preserve \a true if the old values of the array should be preserved, \a false if not. +// \return void +// +// This function resizes the array using the given size to \f$ m \times n \f$. During this +// operation, new dynamic memory may be allocated in case the capacity of the array is too +// small. Note that this function may invalidate all existing views (submatrices, rows, columns, +// ...) on the array if it is used to shrink the array. Additionally, the resize operation +// potentially changes all array elements. In order to preserve the old array values, the +// \a preserve flag can be set to \a true. However, new array elements are not initialized! +// +// The following example illustrates the resize operation of a \f$ 2 \times 4 \f$ array to a +// \f$ 4 \times 2 \f$ array. The new, uninitialized elements are marked with \a x: + + \f[ + \left(\begin{array}{*{4}{c}} + 1 & 2 & 3 & 4 \\ + 5 & 6 & 7 & 8 \\ + \end{array}\right) + + \Longrightarrow + + \left(\begin{array}{*{2}{c}} + 1 & 2 \\ + 5 & 6 \\ + x & x \\ + x & x \\ + \end{array}\right) + \f] +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +void DynamicArray::resize( std::array< size_t, N > const& dims, bool preserve ) +{ + BLAZE_USER_ASSERT( N == n, "invalid dimensionality specified" ); + + using std::swap; + using blaze::min; + + // return if no change is requested + if( ArrayDimAllOf( + dims_, [&]( size_t i ) { return dims_[i] == dims[i]; } ) ) { + return; + } + + const size_t nn( addPadding( dims[0] ) ); + + size_t new_capacity = nn; + for( size_t i = 1; i < n; ++i ) { + new_capacity *= dims[i]; + } + + if( preserve ) + { + Type* BLAZE_RESTRICT v = allocate( new_capacity ); + +// const size_t min_m( min( m, m_ ) ); +// const size_t min_n( min( n, n_ ) ); +// const size_t min_o( min( o, o_ ) ); +// const size_t min_l( min( l, l_ ) ); +// +// for( size_t c = 0UL; c < min_l; ++c ) { +// for( size_t k = 0UL; k < min_o; ++k ) { +// for( size_t i = 0UL; i < min_m; ++i ) { +// transfer( v_ + ( ( k + c * o_ ) * m_ + i ) * nn_, +// v_ + ( ( k + c * o_ ) * m_ + i ) * nn_ + min_n, +// v + ( ( k + c * o ) * m + i ) * nn ); +// } +// } +// } + + swap( v_, v ); + deallocate( v ); + capacity_ = new_capacity; + } + else if( new_capacity > capacity_ ) { + Type* BLAZE_RESTRICT v = allocate( new_capacity ); + swap( v_, v ); + deallocate( v ); + capacity_ = new_capacity; + } + + dims_ = dims; + nn_ = nn; + + if( IsVectorizable_v< Type > ) { + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { v_[i] = Type(); } ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Extending the size of the array. +// +// \param m Number of additional rows. +// \param n Number of additional columns. +// \param preserve \a true if the old values of the array should be preserved, \a false if not. +// \return void +// +// This function increases the array size by \a m rows and \a n columns. During this operation, +// new dynamic memory may be allocated in case the capacity of the array is too small. Therefore +// this function potentially changes all array elements. In order to preserve the old array +// values, the \a preserve flag can be set to \a true. However, new array elements are not +// initialized! +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void DynamicArray::extend( std::array< size_t, N > const& dims, bool preserve ) +{ + BLAZE_USER_ASSERT( N == n, "invalid dimensionality specified" ); + + std::array< size_t, N > newdims; + ArrayDimForEach( + dims_, [&]( size_t i ) { newdims[i] = dims_[i] + dims[i]; } ); + resize( newdims, preserve ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Setting the minimum capacity of the array. +// +// \param elements The new minimum capacity of the dense array. +// \return void +// +// This function increases the capacity of the dense array to at least \a elements elements. +// The current values of the array elements are preserved. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void DynamicArray::reserve( size_t elements ) +{ + using std::swap; + + if( elements > capacity_ ) + { + // Allocating a new array + Type* BLAZE_RESTRICT tmp = allocate( elements ); + + // Initializing the new array + transfer( v_, v_ + capacity_, tmp ); + + if( IsVectorizable_v ) { + for( size_t i = capacity_; i < elements; ++i ) + tmp[i] = Type(); + } + + // Replacing the old array + swap( tmp, v_ ); + deallocate( tmp ); + capacity_ = elements; + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Requesting the removal of unused capacity. +// +// \return void +// +// This function minimizes the capacity of the array by removing unused capacity. Please note +// that due to padding the capacity might not be reduced exactly to rows() times columns(). +// Please also note that in case a reallocation occurs, all iterators (including end() iterators), +// all pointers and references to elements of this array are invalidated. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void DynamicArray::shrinkToFit() +{ + if( ( l_ * o_ * m_ * nn_ ) < capacity_ ) { + DynamicArray( *this ).swap( *this ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Swapping the contents of two matrices. +// +// \param m The array to be swapped. +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void DynamicArray::swap( DynamicArray& m ) noexcept +{ + using std::swap; + + swap( dims_ , m.dims_ ); + swap( capacity_, m.capacity_ ); + swap( v_ , m.v_ ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Add the necessary amount of padding to the given value. +// +// \param value The value to be padded. +// \return The padded value. +// +// This function increments the given \a value by the necessary amount of padding based on the +// vector's data type \a Type. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray::addPadding( size_t value ) noexcept +{ + if( usePadding && IsVectorizable_v ) + return nextMultiple( value, SIMDSIZE ); + return value; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\briefInitialize the dimensions array. +// +// \param value The dimensions for this DynamicArray. +// \return The dimensions array. +// +// This function initializes the internal dimensions array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline std::array< size_t, N > DynamicArray::initDimensions( Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + // the last given dimension is always the lowest + const size_t indices[] = { dims... }; + + std::array< size_t, N > result; + for( size_t i = 0; i != N; ++i ) { + result[i] = indices[N - i - 1]; + } + return result; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\briefInitialize the dimensions array. +// +// \param value The dimensions for this DynamicArray. +// \return The dimensions array. +// +// This function initializes the internal dimensions array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline std::array< size_t , N > DynamicArray< N, Type >::initDimensions( const std::array< size_t, N >& dims ) noexcept +{ + return dims; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate the capacity for the array. +// +// \return The array capacity. +// +// This function calculates the overall needed capacity for the array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray::calcCapacity() const noexcept +{ + size_t capacity = nn_; + for( size_t i = 1; i < N; ++i ) { + capacity *= dims_[i]; + } + return capacity; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline size_t DynamicArray::row_index( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + size_t indices[] = { dims..., i, 0 }; + + size_t idx = 0UL; + for( size_t i = N - 1; i > 1; --i ) { + BLAZE_USER_ASSERT(indices[N - i - 1] < dims_[i], "Invalid access index" ); + idx = (idx + indices[N - i - 1]) * dims_[i - 1]; + } + + BLAZE_USER_ASSERT(indices[N - 2] < dims_[1], "Invalid access index" ); + BLAZE_USER_ASSERT(indices[N - 1] < dims_[0], "Invalid access index" ); + + return (idx + indices[N - 2]) * nn_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate element index. +// +// \param value The index-array for the element access. +// \return The element index. +// +// This function calculates the overall element index into the underlying memory from the ND indices +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +inline size_t DynamicArray::index( Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + size_t indices[] = { size_t(dims)... }; + + size_t idx = 0UL; + for( size_t i = N - 1; i > 1; --i ) { + BLAZE_USER_ASSERT(indices[N - i] < dims_[i], "Invalid access index" ); + idx = (idx + indices[N - i - 1]) * dims_[i - 1]; + } + + BLAZE_USER_ASSERT(indices[N - 2] < dims_[1], "Invalid access index" ); + BLAZE_USER_ASSERT(indices[N - 1] < dims_[0], "Invalid access index" ); + + return (idx + indices[N - 2]) * nn_ + indices[N - 1]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate element index. +// +// \param value The index-array for the element access. +// \return The element index. +// +// This function calculates the overall element index into the underlying memory from the ND indices +*/ +// 3 3 2 2 1 0 0 +// ( ( ( c + 0 ) * o_ + k ) * m_ + i ) * nn_ + j +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray::index( std::array< size_t, N > const& indices ) const noexcept +{ + size_t idx = 0UL; + for( size_t i = N - 1; i > 1; --i ) { + BLAZE_USER_ASSERT( indices[i] < dims_[i], "Invalid access index" ); + idx = (idx + indices[i]) * dims_[i - 1]; + } + + BLAZE_USER_ASSERT(indices[1] < dims_[1], "Invalid access index" ); + BLAZE_USER_ASSERT(indices[0] < dims_[0], "Invalid access index" ); + + return (idx + indices[1]) * nn_ + indices[0]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline constexpr std::array< size_t, N > const& DynamicArray< N, Type >::dimensions() const noexcept +{ + return dims_; +} +//************************************************************************************************* + + + +//================================================================================================= +// +// NUMERIC FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief In-place transpose of the array. +// +// \return Reference to the transposed array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray& DynamicArray::transpose() +{ +// if( l_ == n_ && o_ == n_ && m_ == n_ ) +// { +// transposeGeneral( *this ); +// } +// else +// { +// DynamicArray tmp( trans( *this ) ); +// this->swap( tmp ); +// } + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place transpose of the array. +// +// \return Reference to the transposed array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename T > // Type of the mapping indices +inline DynamicArray& DynamicArray::transpose( const T* indices, size_t n ) +{ +// if( l_ == n_ && o_ == n_ && m_ == n_ ) +// { +// transposeGeneral( *this, indices, n ); +// } +// else +// { +// DynamicArray tmp( trans(*this, indices, n ) ); +// this->swap( tmp ); +// } + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place conjugate transpose of the array. +// +// \return Reference to the transposed array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline DynamicArray& DynamicArray::ctranspose() +{ +// constexpr size_t block( BLOCK_SIZE ); +// +// if( o_ == n_ && m_ == n_ ) +// { +// for( size_t ii=0UL; ii // Data type of the array +template< typename T > // Type of the mapping indices +inline DynamicArray& DynamicArray::ctranspose( const T* indices, size_t n ) +{ +// constexpr size_t block( BLOCK_SIZE ); +// +// if( o_ == n_ && m_ == n_ ) +// { +// for( size_t ii=0UL; ii A; + // ... Resizing and initialization + A *= 4; // Scaling of the array + A.scale( 4 ); // Same effect as above + \endcode +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename Other > // Data type of the scalar value +inline DynamicArray& DynamicArray::scale( const Other& scalar ) +{ + ArrayForEach( dims_, [&]( size_t i ) { v_[i] += scalar; } ); + return *this; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// DEBUGGING FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Returns whether the invariants of the dynamic array are intact. +// +// \return \a true in case the dynamic array's invariants are intact, \a false otherwise. +// +// This function checks whether the invariants of the dynamic array are intact, i.e. if its +// state is valid. In case the invariants are intact, the function returns \a true, else it +// will return \a false. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool DynamicArray::isIntact() const noexcept +{ + if( calcCapacity() > capacity_ ) + return false; + + if (IsVectorizable_v) { + bool is_intact = true; + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { + if( v_[i] != Type() ) + is_intact = false; + } ); + return is_intact; + } + + return true; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TEMPLATE EVALUATION FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Returns whether the array can alias with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this array, \a false if not. +// +// This function returns whether the given address can alias with the array. In contrast +// to the isAliased() function this function is allowed to use compile time expressions +// to optimize the evaluation. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename Other > // Data type of the foreign expression +inline bool DynamicArray::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( alias ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the array is aliased with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this array, \a false if not. +// +// This function returns whether the given address is aliased with the array. In contrast +// to the canAlias() function this function is not allowed to use compile time expressions +// to optimize the evaluation. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename Other > // Data type of the foreign expression +inline bool DynamicArray::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( alias ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the array is properly aligned in memory. +// +// \return \a true in case the array is aligned, \a false if not. +// +// This function returns whether the array is guaranteed to be properly aligned in memory, i.e. +// whether the beginning and the end of each row/column of the array are guaranteed to conform +// to the alignment restrictions of the element type \a Type. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool DynamicArray::isAligned() const noexcept +{ + return ( usePadding || dims_[0] % SIMDSIZE == 0UL ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the array can be used in SMP assignments. +// +// \return \a true in case the array can be used in SMP assignments, \a false if not. +// +// This function returns whether the array can be used in SMP assignments. In contrast to the +// \a smpAssignable member enumeration, which is based solely on compile time information, this +// function additionally provides runtime information (as for instance the current number of +// rows and/or columns of the array). +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool DynamicArray::canSMPAssign() const noexcept +{ + return ( capacity_ >= SMP_DMATASSIGN_THRESHOLD ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Load of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \return The loaded SIMD element. +// +// This function performs a load of a specific SIMD element of the dense array. The row index +// must be smaller than the number of rows and the column index must be smaller then the number +// of columns. Additionally, the column index (in case of a array) or the row index +// (in case of a column-major array) must be a multiple of the number of values inside the +// SIMD element. This function must \b NOT be called explicitly! It is used internally for the +// performance optimized evaluation of expression templates. Calling this function explicitly +// might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType + DynamicArray::load( Dims... dims ) const noexcept +{ + if( usePadding ) + return loada( dims... ); + else + return loadu( dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Aligned load of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \return The loaded SIMD element. +// +// This function performs an aligned load of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType + DynamicArray::loada( Dims... dims ) const noexcept +{ + using blaze::loada; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims ) ), "Invalid alignment detected" ); + + return loada( v_ + index( dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Unaligned load of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \return The loaded SIMD element. +// +// This function performs an unaligned load of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType + DynamicArray::loadu( Dims... dims ) const noexcept +{ + using blaze::loadu; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); + + return loadu( v_ + index( dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs a store of a specific SIMD element of the dense array. The row index +// must be smaller than the number of rows and the column index must be smaller than the number +// of columns. Additionally, the column index (in case of a array) or the row index +// (in case of a column-major array) must be a multiple of the number of values inside the +// SIMD element. This function must \b NOT be called explicitly! It is used internally for the +// performance optimized evaluation of expression templates. Calling this function explicitly +// might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + DynamicArray::store( const SIMDType& value, Dims... dims ) noexcept +{ + if( usePadding ) + storea( value, dims... ); + else + storeu( value, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Aligned store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned store of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + DynamicArray::storea( const SIMDType& value, Dims... dims ) noexcept +{ + using blaze::storea; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); + + storea( v_ + index( dims... ), value ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Unaligned store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an unaligned store of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + DynamicArray::storeu( const SIMDType& value, Dims... dims ) noexcept +{ + using blaze::storeu; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); + + storeu( v_ + index( dims... ), value ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Aligned, non-temporal store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned, non-temporal store of a specific SIMD element of the +// dense array. The row index must be smaller than the number of rows and the column index +// must be smaller than the number of columns. Additionally, the column index (in case of a +// array) or the row index (in case of a column-major array) must be a multiple +// of the number of values inside the SIMD element. This function must \b NOT be called +// explicitly! It is used internally for the performance optimized evaluation of expression +// templates. Calling this function explicitly might result in erroneous results and/or in +// compilation errors. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + DynamicArray::stream( const SIMDType& value, Dims... dims ) noexcept +{ + using blaze::stream; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); + + stream( v_ + index( dims... ), value ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Default implementation of the assignment of a dense array. +// +// \param rhs The right-hand side dense array to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::assign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + + const size_t jpos( dims_[0] & size_t(-2) ); + BLAZE_INTERNAL_ASSERT( ( dims_[0] - ( dims_[0] % 2UL ) ) == jpos, "Invalid end calculation" ); + + ArrayForEachGrouped( + dims_, nn_, [&]( size_t i, std::array< size_t, N > const& dims ) { + v_[i] = ( ~rhs )( dims ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief SIMD optimized implementation of the assignment of a dense array. +// +// \param rhs The right-hand side dense array to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::assign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + + constexpr bool remainder( !usePadding || !IsPadded_v ); + + const size_t jpos( ( remainder )?( dims_[0] & size_t(-SIMDSIZE) ):( dims_[0] ) ); + BLAZE_INTERNAL_ASSERT( !remainder || ( dims_[0] - ( dims_[0] % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); + +// if( usePadding && useStreaming && +// ( o_*m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) ) +// { +// for (size_t k=0UL; k right((~rhs).begin(i, k)); +// +// for (; j right((~rhs).begin(i, k)); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::addAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedAddAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + +// for (size_t k=0UL; k // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::addAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedAddAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + + constexpr bool remainder( !usePadding || !IsPadded_v ); + + for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); + + for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::subAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedSubAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + +// for (size_t k=0UL; k // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::subAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedSubAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + + constexpr bool remainder( !usePadding || !IsPadded_v ); + + for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); + + for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::schurAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + +// const size_t jpos( n_ & size_t(-2) ); +// BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" ); +// +// for (size_t k=0UL; k // Data type of the array +template< typename MT > // Type of the right-hand side dense array +inline auto DynamicArray::schurAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + + constexpr bool remainder( !usePadding || !IsPadded_v ); + + for (size_t k=0UL; k right((~rhs).begin(i, k)); + + for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j // Data type of the array +inline void reset( DynamicArray& m ); + +template< size_t N // The dimensionality of the array + , typename Type // Data type of the array + , typename... Dims > // list of row indices +inline void reset( DynamicArray& m, size_t i, Dims... dims ); + +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void clear( DynamicArray& m ); + +template< bool RF + , size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool isDefault( const DynamicArray& m ); + +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool isIntact( const DynamicArray& m ) noexcept; + +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void swap( DynamicArray& a, DynamicArray& b ) noexcept; +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Resetting the given dynamic array. +// \ingroup dynamic_array +// +// \param m The array to be resetted. +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void reset( DynamicArray& m ) +{ + m.reset(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reset the specified row/column of the given dynamic array. +// \ingroup dynamic_array +// +// \param m The array to reset. +// \param i The index of the row/column to reset. +// \param k The index of the page to reset. +// \return void +// +// This function resets the values in the specified row/column of the given dynamic array to +// their default value. In case the given array is a \a rowMajor array the function resets the +// values in row \a i, if it is a \a columnMajor array the function resets the values in column +// \a i. Note that the capacity of the row/column remains unchanged. +*/ +template< size_t N // The dimensionality of the array + , typename Type // Data type of the array + , typename... Dims > // list of row indices +inline void reset( DynamicArray& m, size_t i, Dims... dims ) +{ + m.reset( i, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Clearing the given dynamic array. +// \ingroup dynamic_array +// +// \param m The array to be cleared. +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void clear( DynamicArray& m ) +{ + m.clear(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the given dynamic array is in default state. +// \ingroup dynamic_array +// +// \param m The array to be tested for its default state. +// \return \a true in case the given array's rows and columns are zero, \a false otherwise. +// +// This function checks whether the dynamic array is in default (constructed) state, i.e. if +// it's number of rows and columns is 0. In case it is in default state, the function returns +// \a true, else it will return \a false. The following example demonstrates the use of the +// \a isDefault() function: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + if( isDefault( A ) ) { ... } + \endcode + +// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed +// semantics (blaze::relaxed): + + \code + if( isDefault( A ) ) { ... } + \endcode +*/ +template< bool RF // Relaxation flag + , size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool isDefault( const DynamicArray& m ) +{ + auto const& dims = m.dimensions(); + return ArrayDimAllOf( dims, [&]( size_t i ) { return dims[i] == 0; } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the invariants of the given dynamic array are intact. +// \ingroup dynamic_array +// +// \param m The dynamic array to be tested. +// \return \a true in case the given array's invariants are intact, \a false otherwise. +// +// This function checks whether the invariants of the dynamic array are intact, i.e. if its +// state is valid. In case the invariants are intact, the function returns \a true, else it +// will return \a false. The following example demonstrates the use of the \a isIntact() +// function: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + if( isIntact( A ) ) { ... } + \endcode +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline bool isIntact( const DynamicArray& m ) noexcept +{ + return m.isIntact(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Swapping the contents of two dynamic matrices. +// \ingroup dynamic_array +// +// \param a The first array to be swapped. +// \param b The second array to be swapped. +// \return void +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline void swap( DynamicArray& a, DynamicArray& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct HasConstDataAccess< DynamicArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct HasMutableDataAccess< DynamicArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct IsAligned< DynamicArray > + : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCONTIGUOUS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct IsContiguous< DynamicArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct IsPadded< DynamicArray > + : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct IsResizable< DynamicArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSHRINKABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +struct IsShrinkable< DynamicArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// template< typename T1, typename T2 > +// struct AddTraitEval2< T1, T2 +// , EnableIf_t< IsArray_v && +// IsArray_v && +// ( IsDenseArray_v || IsDenseArray_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultSize_v ) > > +// { +// using ET1 = ElementType_t; +// using ET2 = ElementType_t; +// +// using Type = DynamicArray< AddTrait_t >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// template< typename T1, typename T2 > +// struct SubTraitEval2< T1, T2 +// , EnableIf_t< IsArray_v && +// IsArray_v && +// ( IsDenseArray_v || IsDenseArray_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) > > +// { +// using ET1 = ElementType_t; +// using ET2 = ElementType_t; +// +// using Type = DynamicArray< SubTrait_t >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SCHURTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// template< typename T1, typename T2 > +// struct SchurTraitEval2< T1, T2 +// , EnableIf_t< IsDenseArray_v && +// IsDenseArray_v && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) > > +// { +// using ET1 = ElementType_t; +// using ET2 = ElementType_t; +// +// using Type = DynamicArray< MultTrait_t >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename ET1, typename T2 > +struct MultTraitEval2< DynamicArray, T2 + , EnableIf_t< IsNumeric_v > > +{ + using Type = DynamicArray< N, MultTrait_t >; +}; + +template< typename T1, size_t N, typename ET2 > +struct MultTraitEval2< T1, DynamicArray + , EnableIf_t< IsNumeric_v > > +{ + using Type = DynamicArray< N, MultTrait_t >; +}; + +// template< typename T1, typename T2 > +// struct MultTraitEval2< T1, T2 +// , EnableIf_t< IsArray_v && +// IsArray_v && +// ( IsDenseArray_v || IsDenseArray_v ) && +// ( ( Size_v == DefaultSize_v && +// ( !IsSquare_v || Size_v == DefaultSize_v ) ) || +// ( Size_v == DefaultSize_v && +// ( !IsSquare_v || Size_v == DefaultSize_v ) ) || +// ( Size_v == DefaultSize_v && +// ( !IsSquare_v || Size_v == DefaultSize_v ) ) ) && +// ( ( MaxSize_v == DefaultMaxSize_v && +// ( !IsSquare_v || MaxSize_v == DefaultMaxSize_v ) ) || +// ( MaxSize_v == DefaultMaxSize_v && +// ( !IsSquare_v || MaxSize_v == DefaultMaxSize_v ) ) || +// ( MaxSize_v == DefaultMaxSize_v && +// ( !IsSquare_v || MaxSize_v == DefaultMaxSize_v ) ) ) > > +// { +// using ET1 = ElementType_t; +// using ET2 = ElementType_t; +// +// using Type = DynamicArray< MultTrait_t >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename ET1, typename T2 > +struct DivTraitEval2< DynamicArray, T2 + , EnableIf_t< IsNumeric_v > > +{ + using Type = DynamicArray< N, DivTrait_t >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MAPTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename ET, typename OP > +struct UnaryMapTraitEval2< DynamicArray, OP> +{ + using Type = DynamicArray< N, MapTrait_t >; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename ET1, typename ET2, typename OP > +struct BinaryMapTraitEval2< DynamicArray< N, ET1 > , DynamicArray< N, ET2 >, OP > +{ + using Type = DynamicArray< N, MapTrait_t >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPANDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// template< typename T // Type to be expanded +// , size_t E > // Compile time expansion +// struct ExpandTraitEval2< T, E +// , EnableIf_t< IsDenseMatrix_v && +// ( ( E == inf ) || +// ( ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) ) ) > > +// { +// using Type = DynamicArray< ElementType_t >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// RAVELTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// FIXME: this needs to go into math/dense/DynamicMatrix.h +// template< typename T > // Type to be expanded +// struct RavelTraitEval2< T +// , EnableIf_t< IsDenseArray_v && +// ( ( ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) && +// ( Size_v == DefaultSize_v ) && +// ( MaxSize_v == DefaultMaxSize_v ) ) ) > > +// { +// using Type = DynamicVector< ElementType_t, rowVector >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HIGHTYPE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// template< typename T1, typename T2 > +// struct HighType< DynamicArray, DynamicArray > +// { +// using Type = DynamicArray< typename HighType::Type >; +// }; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// LOWTYPE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +// template< typename T1, typename T2 > +// struct LowType< DynamicArray, DynamicArray > +// { +// using Type = DynamicArray< typename LowType::Type >; +// }; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/dense/DynamicTensor.h b/blaze_tensor/math/dense/DynamicTensor.h index c023410..9b49655 100644 --- a/blaze_tensor/math/dense/DynamicTensor.h +++ b/blaze_tensor/math/dense/DynamicTensor.h @@ -1639,7 +1639,7 @@ void DynamicTensor::resize( size_t o, size_t m, size_t n, bool preserve ) for (size_t k=0UL; k + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base class for all binary array map expression templates. +// \ingroup math +// +// The ArrArrMapExpr class serves as a tag for all expression templates that implement a binary +// array map operation. All classes, that represent a binary array map operation and that are +// used within the expression template environment of the Blaze library have to derive publicly +// from this class in order to qualify as binary array map expression template. Only in case a +// class is derived publicly from the ArrArrMapExpr base class, the IsArrArrMapExpr type trait +// recognizes the class as valid binary array map expression template. +*/ +template< typename MT > // Array base type of the expression +struct ArrArrMapExpr + : public BinaryMapExpr +{}; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/ArrMapExpr.h b/blaze_tensor/math/expressions/ArrMapExpr.h new file mode 100644 index 0000000..0c28f53 --- /dev/null +++ b/blaze_tensor/math/expressions/ArrMapExpr.h @@ -0,0 +1,74 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/ArrMapExpr.h +// \brief Header file for the ArrMapExpr base class +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRMAPEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRMAPEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base class for all unary array map expression templates. +// \ingroup math +// +// The ArrMapExpr class serves as a tag for all expression templates that represent a unary map +// operation on a array. All classes, that represent a unary array map operation and that are +// used within the expression template environment of the Blaze library have to derive publicly +// from this class in order to qualify as unary array map expression template. Only in case a +// class is derived publicly from the ArrMapExpr base class, the IsArrMapExpr type trait +// recognizes the class as valid unary array map expression template. +*/ +template< typename MT > // Tensor base type of the expression +struct ArrMapExpr + : public UnaryMapExpr +{}; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/ArrReduceExpr.h b/blaze_tensor/math/expressions/ArrReduceExpr.h new file mode 100644 index 0000000..a2d4e9d --- /dev/null +++ b/blaze_tensor/math/expressions/ArrReduceExpr.h @@ -0,0 +1,75 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/ArrReduceExpr.h +// \brief Header file for the ArrReduceExpr base class +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRREDUCEEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRREDUCEEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base class for all array reduction expression templates. +// \ingroup math +// +// The ArrReduceExpr class serves as a tag for all expression templates that implement a array +// reduction. All classes, that represent a array reduction and and that are used within the +// expression template environment of the Blaze library have to derive publicly from this class +// in order to qualify as array reduction expression template. Only in case a class is derived +// publicly from the ArrReduceExpr base class, the IsArrReduceExpr type trait recognizes the +// class as valid array reduction expression template. +*/ +template< typename VT // Tensor base type of the expression + , size_t RF > // Reduction flag +struct ArrReduceExpr + : public ReduceExpr +{}; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/ArrScalarDivExpr.h b/blaze_tensor/math/expressions/ArrScalarDivExpr.h new file mode 100644 index 0000000..fd0a569 --- /dev/null +++ b/blaze_tensor/math/expressions/ArrScalarDivExpr.h @@ -0,0 +1,74 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/ArrScalarDivExpr.h +// \brief Header file for the ArrScalarDivExpr base class +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRSCALARDIVEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRSCALARDIVEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base class for all array/scalar division expression templates. +// \ingroup math +// +// The ArrScalarDivExpr class serves as a tag for all expression templates that implement a +// array/scalar division. All classes, that represent a array/scalar division and that are +// used within the expression template environment of the Blaze library have to derive publicly +// from this class in order to qualify as array/scalar division expression template. Only in +// case a class is derived publicly from the ArrScalarDivExpr base class, the IsArrScalarDivExpr +// type trait recognizes the class as valid array/scalar division expression template. +*/ +template< typename MT > // Array base type of the expression +struct ArrScalarDivExpr + : public DivExpr +{}; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/ArrScalarMultExpr.h b/blaze_tensor/math/expressions/ArrScalarMultExpr.h new file mode 100644 index 0000000..f6658b1 --- /dev/null +++ b/blaze_tensor/math/expressions/ArrScalarMultExpr.h @@ -0,0 +1,75 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/ArrScalarMultExpr.h +// \brief Header file for the ArrScalarMultExpr base class +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRSCALARMULTEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRSCALARMULTEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base class for all array/scalar multiplication expression templates. +// \ingroup math +// +// The ArrScalarMultExpr class serves as a tag for all expression templates that implement a +// array/scalar multiplication. All classes, that represent a array/scalar multiplication +// and that are used within the expression template environment of the Blaze library have +// to derive publicly from this class in order to qualify as array/scalar multiplication +// expression template. Only in case a class is derived publicly from the ArrScalarMultExpr +// base class, the IsArrScalarMultExpr type trait recognizes the class as valid array/scalar +// multiplication expression template. +*/ +template< typename MT > // Array base type of the expression +struct ArrScalarMultExpr + : public MultExpr +{}; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/Array.h b/blaze_tensor/math/expressions/Array.h new file mode 100644 index 0000000..8d2c46a --- /dev/null +++ b/blaze_tensor/math/expressions/Array.h @@ -0,0 +1,1740 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/Array.h +// \brief Header file for the Array base class +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRAY_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_ARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\defgroup array Arrays +// \ingroup math +*/ +/*!\brief Base class for arrays. +// \ingroup array +// +// The Array class is a base class for all dense and sparse array classes within the Blaze +// library. It provides an abstraction from the actual type of the array, but enables a +// conversion back to this type via the 'Curiously Recurring Template Pattern' (CRTP). +*/ +template< typename TT > // Type of the array +struct Array +{ + //**Type definitions**************************************************************************** + using ArrayType = TT; //!< Type of the array. + //********************************************************************************************** + + //**Non-const conversion operator*************************************************************** + /*!\brief Conversion operator for non-constant arrays. + // + // \return Reference of the actual type of the array. + */ + BLAZE_ALWAYS_INLINE constexpr ArrayType& operator~() noexcept { + return *static_cast( this ); + } + //********************************************************************************************** + + //**Const conversion operator******************************************************************* + /*!\brief Conversion operator for constant arrays. + // + // \return Constant reference of the actual type of the array. + */ + BLAZE_ALWAYS_INLINE constexpr const ArrayType& operator~() const noexcept { + return *static_cast( this ); + } + //********************************************************************************************** +}; +//************************************************************************************************* + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication assignment operator for the multiplication of two arrays (\f$ A*=B \f$). +// \ingroup array +// +// \param lhs The left-hand side array for the multiplication. +// \param rhs The right-hand side array for the multiplication. +// \return Reference to the left-hand side array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current number of columns of \a lhs and the current number of rows of \a rhs +// don't match, a \a std::invalid_argument is thrown. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +inline TT1& operator*=( Array& lhs, const Array& rhs ) +{ + ResultType_t tmp( (~lhs) * (~rhs) ); + (~lhs) = std::move( tmp ); + return (~lhs); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication assignment operator for the multiplication of a temporary array with +// another array (\f$ A*=B \f$). +// \ingroup array +// +// \param lhs The left-hand side temporary array for the multiplication. +// \param rhs The right-hand side array for the multiplication. +// \return Reference to the left-hand side array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current number of columns of \a lhs and the current number of rows of \a rhs +// don't match, a \a std::invalid_argument is thrown. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +inline TT1& operator*=( Array&& lhs, const Array& rhs ) +{ + return (~lhs) *= (~rhs); +} +/*! \endcond */ +//************************************************************************************************* + + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by setting a single element of an array. +// \ingroup array +// +// \param mat The target array. +// \param i The row index of the element to be set. +// \param j The column index of the element to be set. +// \param k The page index of the element to be set. +// \param value The value to be set to the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool trySet( const Array& mat, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < (~mat).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < (~mat).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( k < (~mat).pages(), "Invalid page access index" ); + + MAYBE_UNUSED( mat, k, i, j, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by adding to a single element of an array. +// \ingroup array +// +// \param mat The target array. +// \param i The row index of the element to be modified. +// \param j The column index of the element to be modified. +// \param k The page index of the element to be modified. +// \param value The value to be added to the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool tryAdd( const Array& mat, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < (~mat).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < (~mat).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( k < (~mat).pages(), "Invalid page access index" ); + + MAYBE_UNUSED( mat, k, i, j, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by subtracting from a single element of an array. +// \ingroup array +// +// \param mat The target array. +// \param i The row index of the element to be modified. +// \param j The column index of the element to be modified. +// \param k The page index of the element to be modified. +// \param value The value to be subtracted from the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool trySub( const Array& mat, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < (~mat).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < (~mat).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( k < (~mat).pages(), "Invalid page access index" ); + + MAYBE_UNUSED( mat, k, i, j, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a single element of an array. +// \ingroup array +// +// \param tens The target array. +// \param i The row index of the element to be modified. +// \param j The column index of the element to be modified. +// \param k The page index of the element to be modified. +// \param value The factor for the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool tryMult( const Array& tens, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < (~tens).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < (~tens).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( k < (~tens).pages(), "Invalid page access index" ); + + MAYBE_UNUSED( tens, k, i, j, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a range of elements of an array. +// \ingroup array +// +// \param tens The target array. +// \param row The index of the first row of the range to be modified. +// \param column The index of the first column of the range to be modified. +// \param page The index of the first page of the range to be modified. +// \param m The number of rows of the range to be modified. +// \param n The number of columns of the range to be modified. +// \param o The number of pages of the range to be modified. +// \param value The factor for the elements. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool + tryMult( const Array& tens, size_t row, size_t column, size_t page, size_t o, size_t m, size_t n, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( row <= (~tens).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( column <= (~tens).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( page <= (~tens).pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( row + m <= (~tens).rows(), "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( column + n <= (~tens).columns(), "Invalid number of columns" ); + BLAZE_INTERNAL_ASSERT( page + o <= (~tens).pages(), "Invalid number of pages" ); + + MAYBE_UNUSED( tens, page, row, column, o, m, n, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a single element of an array. +// \ingroup array +// +// \param mat The target array. +// \param i The row index of the element to be modified. +// \param j The column index of the element to be modified. +// \param k The page index of the element to be modified. +// \param value The divisor for the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , size_t N // number of dimensions + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool tryDiv( const Array& arr, std::array< size_t, N > const& dims, const ET& value ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& arrdims = ( ~arr ).dimensions(); + ArrayDimForEach( arrdims, [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( mat, dims, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a range of elements of an array. +// \ingroup array +// +// \param mat The target array. +// \param row The index of the first row of the range to be modified. +// \param column The index of the first column of the range to be modified. +// \param page The index of the first page of the range to be modified. +// \param m The number of rows of the range to be modified. +// \param n The number of columns of the range to be modified. +// \param o The number of pages of the range to be modified. +// \param value The divisor for the elements. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the array + , size_t M // number of current dimensions + , size_t N // number of dimensions + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool + tryDiv( const Array& arr, std::array< size_t, M > const& currdims, + std::array< size_t, N > const& dims, const ET& value ) +{ + BLAZE_STATIC_ASSERT( M == N ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + ArrayDimForEach( dims, [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( currdims[i] < dims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( arr, currdims, dims, value ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be assigned. +// \param row The row index of the first element to be modified. +// \param column The column index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename MT // Type of the left-hand side array + , typename VT // Type of the right-hand side array + , size_t N > // Number of dimensions to check +BLAZE_ALWAYS_INLINE bool tryAssign( const Array& lhs, const Array& rhs, + std::array< size_t, N > const& dims ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& rhsdims = ( ~rhs ).dimensions(); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( lhs, rhs, dims ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the addition assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be added. +// \param row The row index of the first element to be modified. +// \param column The column index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 // Type of the right-hand side array + , size_t N > // Number of dimensions to check +BLAZE_ALWAYS_INLINE bool tryAddAssign( const Array& lhs, const Array& rhs, + std::array< size_t, N > const& dims ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& rhsdims = ( ~rhs ).dimensions(); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( lhs, rhs, dims ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the subtraction assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be subtracted. +// \param row The row index of the first element to be modified. +// \param column The column index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 // Type of the right-hand side array + , size_t N > // Number of dimensions to check +BLAZE_ALWAYS_INLINE bool trySubAssign( const Array& lhs, const Array& rhs, + std::array< size_t, N > const& dims ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& rhsdims = ( ~rhs ).dimensions(); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( lhs, rhs, dims ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the multiplication assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be multiplied. +// \param band The index of the band the right-hand side array is assigned to. +// \param row The row index of the first element to be modified. +// \param column The column index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 // Type of the right-hand side array + , size_t N > // Number of dimensions to check +BLAZE_ALWAYS_INLINE bool tryMultAssign( const Array& lhs, const Array& rhs, + std::array< size_t, N > const& dims ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& rhsdims = ( ~rhs ).dimensions(); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( lhs, rhs, dims ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the Schur product assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array for the Schur product. +// \param row The row index of the first element to be modified. +// \param column The column index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 // Type of the right-hand side array + , size_t N > // Number of dimensions to check +BLAZE_ALWAYS_INLINE bool trySchurAssign( const Array& lhs, const Array& rhs, + std::array< size_t, N > const& dims ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& rhsdims = ( ~rhs ).dimensions(); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( lhs, rhs, dims ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the division assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array divisor. +// \param row The row index of the first element to be modified. +// \param column The column index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 // Type of the right-hand side array + , size_t N > // Number of dimensions to check +BLAZE_ALWAYS_INLINE bool tryDivAssign( const Array& lhs, const Array& rhs, + std::array< size_t, N > const& dims ) +{ +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& rhsdims = ( ~rhs ).dimensions(); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + } ); +#endif + + MAYBE_UNUSED( lhs, rhs, dims ); + + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Array global functions */ +//@{ +template< typename MT > +BLAZE_ALWAYS_INLINE typename MT::Iterator begin( Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator begin( const Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator cbegin( const Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE typename MT::Iterator end( Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator end( const Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator cend( const Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE constexpr size_t rows( const Array& array ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE constexpr size_t columns( const Array& array ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE constexpr size_t pages( const Array& array ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE constexpr size_t size( const Array& array ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE size_t capacity( const Array& array ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE size_t capacity( const Array& array, size_t i, size_t k ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const Array& array ); + +template< typename MT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const Array& array, size_t i, size_t k ); + +template< typename MT > +BLAZE_ALWAYS_INLINE void resize( Array& array, size_t rows, size_t columns, size_t pages, bool preserve=true ); + +template< typename MT > +BLAZE_ALWAYS_INLINE void shrinkToFit( Array& array ); + +template< typename MT > +BLAZE_ALWAYS_INLINE void transpose( Array& array ); + +template< typename MT, typename T > +BLAZE_ALWAYS_INLINE void transpose( Array& array, const T*, size_t ); + +template< typename MT, typename T > +BLAZE_ALWAYS_INLINE void transpose( Array& array, std::initializer_list ); + +template< typename MT > +BLAZE_ALWAYS_INLINE void ctranspose( Array& array ); + +template< typename MT, typename T > +BLAZE_ALWAYS_INLINE void ctranspose( Array& array, const T*, size_t ); + +template< typename MT, typename T > +BLAZE_ALWAYS_INLINE void ctranspose( Array& array, std::initializer_list ); + + +template< typename MT > +inline const typename MT::ResultType evaluate( const Array& array ); + +template< typename MT > +BLAZE_ALWAYS_INLINE constexpr bool isEmpty( const Array& array ) noexcept; + +template< typename MT > +BLAZE_ALWAYS_INLINE bool isSquare( const Array& array ) noexcept; + +template< typename TT1, typename TT2 > +BLAZE_ALWAYS_INLINE bool isSame( const Array& a, const Array& b ) noexcept; +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// \ingroup array +// +// \param array The given dense or sparse array. +// \param i The row/column index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the given array is a row-major array the function returns an iterator to the first element +// of row \a i, in case it is a column-major array the function returns an iterator to the first +// element of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE typename MT::Iterator begin( Array& array, size_t i, size_t k ) +{ + return (~array).begin(i, k); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// \ingroup array +// +// \param array The given dense or sparse array. +// \param i The row/column index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the given array is a row-major array the function returns an iterator to the first element +// of row \a i, in case it is a column-major array the function returns an iterator to the first +// element of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE typename MT::ConstIterator begin( const Array& array, size_t i, size_t k ) +{ + return (~array).begin(i, k); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// \ingroup array +// +// \param array The given dense or sparse array. +// \param i The row/column index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the given array is a row-major array the function returns an iterator to the first element +// of row \a i, in case it is a column-major array the function returns an iterator to the first +// element of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE typename MT::ConstIterator cbegin( const Array& array, size_t i, size_t k ) +{ + return (~array).cbegin(i, k); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// \ingroup array +// +// \param array The given dense or sparse array. +// \param i The row/column index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the given array is a row-major array the function returns an iterator just past +// the last element of row \a i, in case it is a column-major array the function returns an +// iterator just past the last element of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE typename MT::Iterator end( Array& array, size_t i, size_t k ) +{ + return (~array).end(i, k); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// \ingroup array +// +// \param array The given dense or sparse array. +// \param i The row/column index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the given array is a row-major array the function returns an iterator just past +// the last element of row \a i, in case it is a column-major array the function returns an +// iterator just past the last element of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE typename MT::ConstIterator end( const Array& array, size_t i, size_t k ) +{ + return (~array).end(i, k); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// \ingroup array +// +// \param array The given dense or sparse array. +// \param i The row/column index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the given array is a row-major array the function returns an iterator just past +// the last element of row \a i, in case it is a column-major array the function returns an +// iterator just past the last element of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE typename MT::ConstIterator cend( const Array& array, size_t i, size_t k ) +{ + return (~array).cend(i, k); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the current number of rows of the array. +// \ingroup array +// +// \param array The given array. +// \return The number of rows of the array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE constexpr size_t rows( const Array& array ) noexcept +{ + return (~array).rows(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the current number of columns of the array. +// \ingroup array +// +// \param array The given array. +// \return The number of columns of the array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE constexpr size_t columns( const Array& array ) noexcept +{ + return (~array).columns(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the current number of pages of the array. +// \ingroup array +// +// \param array The given array. +// \return The number of pages of the array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE constexpr size_t pages( const Array& array ) noexcept +{ + return (~array).pages(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the total number of elements of the array. +// \ingroup array +// +// \param array The given array. +// \return The total number of elements of the array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE constexpr size_t size( const Array& array ) noexcept +{ + return (~array).rows() * (~array).columns() * (~array).pages(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the maximum capacity of the array. +// \ingroup array +// +// \param array The given array. +// \return The capacity of the array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE size_t capacity( const Array& array ) noexcept +{ + return (~array).capacity(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the current capacity of the specified row/column. +// \ingroup array +// +// \param array The given array. +// \param i The index of the row/column. +// \return The current capacity of row/column \a i. +// +// This function returns the current capacity of the specified row/column. In case the +// storage order is set to \a rowMajor the function returns the capacity of row \a i, +// in case the storage flag is set to \a columnMajor the function returns the capacity +// of column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE size_t capacity( const Array& array, size_t i, size_t k ) noexcept +{ + return (~array).capacity( i, k ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the total number of non-zero elements in the array +// \ingroup array +// +// \param array The given array. +// \return The number of non-zero elements in the dense array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE size_t nonZeros( const Array& array ) +{ + return (~array).nonZeros(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the number of non-zero elements in the specified row/column. +// \ingroup array +// +// \param array The given array. +// \param i The index of the row/column. +// \return The number of non-zero elements of row/column \a i. +// +// This function returns the current number of non-zero elements in the specified row/column. +// In case the storage order is set to \a rowMajor the function returns the number of non-zero +// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns +// the number of non-zero elements in column \a i. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE size_t nonZeros( const Array& array, size_t i, size_t k ) +{ + return (~array).nonZeros( i, k ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c resize() function for non-resizable arrays. +// \ingroup array +// +// \param array The given array to be resized. +// \param m The new number of rows of the array. +// \param n The new number of columns of the array. +// \param preserve \a true if the old values of the array should be preserved, \a false if not. +// \return void +// \exception std::invalid_argument Array cannot be resized. +// +// This function tries to change the number of rows and columns of a non-resizable array. Since +// the array cannot be resized, in case the specified number of rows and columns is not identical +// to the current number of rows and columns of the array, a \a std::invalid_argument exception +// is thrown. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE DisableIf_t< IsResizable_v > + resize_backend( Array& array, size_t o, size_t m, size_t n, bool preserve ) +{ + MAYBE_UNUSED( preserve ); + + if( (~array).rows() != m || (~array).columns() != n || (~array).pages() != o) { + BLAZE_THROW_INVALID_ARGUMENT( "Array cannot be resized" ); + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c resize() function for resizable, non-square arrays. +// \ingroup array +// +// \param array The given array to be resized. +// \param m The new number of rows of the array. +// \param n The new number of columns of the array. +// \param preserve \a true if the old values of the array should be preserved, \a false if not. +// \return void +// +// This function changes the number of rows and columns of the given resizable, non-square array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE EnableIf_t< IsResizable_v && !IsSquare_v > + resize_backend( Array& array, size_t o, size_t m, size_t n, bool preserve ) +{ + (~array).resize( o, m, n, preserve ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c resize() function for resizable, square arrays. +// \ingroup array +// +// \param array The given array to be resized. +// \param m The new number of rows of the array. +// \param n The new number of columns of the array. +// \param preserve \a true if the old values of the array should be preserved, \a false if not. +// \return void +// \exception std::invalid_argument Invalid resize arguments for square array. +// +// This function changes the number of rows and columns of the given resizable, square array. +*/ +// template< typename MT > // Type of the array +// BLAZE_ALWAYS_INLINE EnableIf_t< IsResizable_v && IsSquare_v > +// resize_backend( Array& array, size_t o, size_t m, size_t n, bool preserve ) +// { +// if( m != n || m != o ) { +// BLAZE_THROW_INVALID_ARGUMENT( "Invalid resize arguments for square array" ); +// } +// +// (~array).resize( m, preserve ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Changing the size of the array. +// \ingroup array +// +// \param array The given array to be resized. +// \param m The new number of rows of the array. +// \param n The new number of columns of the array. +// \param preserve \a true if the old values of the array should be preserved, \a false if not. +// \return void +// \exception std::invalid_argument Invalid resize arguments for square array. +// \exception std::invalid_argument Array cannot be resized. +// +// This function provides a unified interface to resize dense and sparse arrays. In contrast +// to the \c resize() member function, which is only available on resizable array types, this +// function can be used on both resizable and non-resizable arrays. In case the given array +// of type \a MT is resizable (i.e. provides a \c resize function) the type-specific \c resize() +// member function is called. Depending on the type \a MT, this may result in the allocation of +// new dynamic memory and the invalidation of existing views (subarrays, rows, columns, ...). +// Note that in case the array is a compile time square array (as for instance the +// blaze::SymmetricArray adaptor, ...) the specified number of rows must be identical to the +// number of columns. Otherwise a \a std::invalid_argument exception is thrown. If the array +// type \a MT is non-resizable (i.e. does not provide a \c resize() function) and if the specified +// number of rows and columns is not identical to the current number of rows and columns of the +// array, a \a std::invalid_argument exception is thrown. + + \code + blaze::DynamicArray A( 3UL, 3UL ); + resize( A, 5UL, 2UL ); // OK: regular resize operation + + blaze::SymmetricArray< DynamicArray > B( 3UL ); + resize( B, 4UL, 4UL ); // OK: Number of rows and columns is identical + resize( B, 3UL, 5UL ); // Error: Invalid arguments for square array! + + blaze::StaticArray C; + resize( C, 3UL, 3UL ); // OK: No resize necessary + resize( C, 5UL, 2UL ); // Error: Array cannot be resized! + \endcode +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE void resize( Array& array, size_t o, size_t m, size_t n, bool preserve ) +{ + resize_backend( array, o, m, n, preserve ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c shrinkToFit() function for non-shrinkable arrays. +// \ingroup array +// +// \param array The given array to be shrunk. +// \return void +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE DisableIf_t< IsShrinkable_v > + shrinkToFit_backend( Array& array ) +{ + MAYBE_UNUSED( array ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c shrinkToFit() function for shrinkable arrays. +// \ingroup array +// +// \param array The given array to be shrunk. +// \return void +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE EnableIf_t< IsShrinkable_v > + shrinkToFit_backend( Array& array ) +{ + (~array).shrinkToFit(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Requesting the removal of unused capacity. +// \ingroup array +// +// \param array The given array to be shrunk. +// \return void +// +// This function tries to minimize the capacity of the array by removing unused capacity. +// Please note that in case of a shrinkable array, due to padding the capacity might not be +// reduced exactly to the number of rows times the number of columns. Please also note that +// in case a reallocation occurs, all iterators (including end() iterators), all pointers and +// references to elements of this array are invalidated. In case of an unshrinkable array +// the function has no effect. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE void shrinkToFit( Array& array ) +{ + shrinkToFit_backend( array ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place transpose of the given array. +// \ingroup array +// +// \param array The given array to be transposed. +// \return void +// \exception std::logic_error Array cannot be transposed. +// +// This function transposes the given array in-place. The function fails if ... +// +// - ... the given array has a fixed size and is non-square; +// - ... the given array is a triangular array; +// - ... the given subarray affects the restricted parts of a triangular array; +// - ... the given subarray would cause non-deterministic results in a symmetric/Hermitian array. +// +// In all failure cases a \a std::logic_error exception is thrown. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE void transpose( Array& array ) +{ + (~array).transpose( ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place transpose of the given array. +// \ingroup array +// +// \param array The given array to be transposed. +// \return void +// \exception std::logic_error Array cannot be transposed. +// +// This function transposes the given array in-place. The function fails if ... +// +// - ... the given array has a fixed size and is non-square; +// - ... the given array is a triangular array; +// - ... the given subarray affects the restricted parts of a triangular array; +// - ... the given subarray would cause non-deterministic results in a symmetric/Hermitian array. +// +// In all failure cases a \a std::logic_error exception is thrown. +*/ +template< typename MT // Type of the array + , typename T > // Type of the index initializer +BLAZE_ALWAYS_INLINE void transpose( Array& array, const T* indices, size_t n ) +{ + (~array).transpose( indices, n ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place transpose of the given array. +// \ingroup array +// +// \param array The given array to be transposed. +// \return void +// \exception std::logic_error Array cannot be transposed. +// +// This function transposes the given array in-place. The function fails if ... +// +// - ... the given array has a fixed size and is non-square; +// - ... the given array is a triangular array; +// - ... the given subarray affects the restricted parts of a triangular array; +// - ... the given subarray would cause non-deterministic results in a symmetric/Hermitian array. +// +// In all failure cases a \a std::logic_error exception is thrown. +*/ +template< typename MT // Type of the array + , typename T > // Type of the index initializer +BLAZE_ALWAYS_INLINE void transpose( Array& array, std::initializer_list indices ) +{ + (~array).transpose( indices.begin(), indices.size() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place conjugate transpose of the given array. +// \ingroup array +// +// \param array The given array to be transposed. +// \return void +// \exception std::logic_error Array cannot be transposed. +// +// This function transposes the given array in-place. The function fails if ... +// +// - ... the given array has a fixed size and is non-square; +// - ... the given array is a triangular array; +// - ... the given subarray affects the restricted parts of a triangular array; +// - ... the given subarray would cause non-deterministic results in a symmetric/Hermitian array. +// +// In all failure cases a \a std::logic_error exception is thrown. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE void ctranspose( Array& array ) +{ + (~array).ctranspose(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place conjugate transpose of the given array. +// \ingroup array +// +// \param array The given array to be transposed. +// \return void +// \exception std::logic_error Array cannot be transposed. +// +// This function transposes the given array in-place. The function fails if ... +// +// - ... the given array has a fixed size and is non-square; +// - ... the given array is a triangular array; +// - ... the given subarray affects the restricted parts of a triangular array; +// - ... the given subarray would cause non-deterministic results in a symmetric/Hermitian array. +// +// In all failure cases a \a std::logic_error exception is thrown. +*/ +template< typename MT // Type of the array + , typename T > // Type of the index initializer +BLAZE_ALWAYS_INLINE void ctranspose( Array& array, const T* indices, size_t n ) +{ + (~array).ctranspose( indices, n ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief In-place conjugate transpose of the given array. +// \ingroup array +// +// \param array The given array to be transposed. +// \return void +// \exception std::logic_error Array cannot be transposed. +// +// This function transposes the given array in-place. The function fails if ... +// +// - ... the given array has a fixed size and is non-square; +// - ... the given array is a triangular array; +// - ... the given subarray affects the restricted parts of a triangular array; +// - ... the given subarray would cause non-deterministic results in a symmetric/Hermitian array. +// +// In all failure cases a \a std::logic_error exception is thrown. +*/ +template< typename MT // Type of the array + , typename T > // Type of the index initializer +BLAZE_ALWAYS_INLINE void ctranspose( Array& array, std::initializer_list indices ) +{ + (~array).ctranspose( indices.begin(), indices.size() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Evaluates the given array expression. +// \ingroup array +// +// \param array The array to be evaluated. +// \return The result of the evaluated array expression. +// +// This function forces an evaluation of the given array expression and enables an automatic +// deduction of the correct result type of an operation. The following code example demonstrates +// its intended use for the multiplication of a lower and a strictly lower dense array: + + \code + using blaze::DynamicArray; + using blaze::LowerArray; + using blaze::StrictlyLowerArray; + + LowerArray< DynamicArray > A; + StrictlyLowerArray< DynamicArray > B; + // ... Resizing and initialization + + auto C = evaluate( A * B ); + \endcode + +// In this scenario, the \a evaluate() function assists in deducing the exact result type of +// the operation via the 'auto' keyword. Please note that if \a evaluate() is used in this +// way, no temporary array is created and no copy operation is performed. Instead, the result +// is directly written to the target array due to the return value optimization (RVO). However, +// if \a evaluate() is used in combination with an explicit target type, a temporary will be +// created and a copy operation will be performed if the used type differs from the type +// returned from the function: + + \code + StrictlyLowerArray< DynamicArray > D( A * B ); // No temporary & no copy operation + LowerArray< DynamicArray > E( A * B ); // Temporary & copy operation + DynamicArray F( A * B ); // Temporary & copy operation + D = evaluate( A * B ); // Temporary & copy operation + \endcode + +// Sometimes it might be desirable to explicitly evaluate a sub-expression within a larger +// expression. However, please note that \a evaluate() is not intended to be used for this +// purpose. This task is more elegantly and efficiently handled by the \a eval() function: + + \code + blaze::DynamicArray A, B, C, D; + + D = A + evaluate( B * C ); // Unnecessary creation of a temporary array + D = A + eval( B * C ); // No creation of a temporary array + \endcode + +// In contrast to the \a evaluate() function, \a eval() can take the complete expression into +// account and therefore can guarantee the most efficient way to evaluate it. +*/ +template< typename MT > // Type of the array +inline const typename MT::ResultType evaluate( const Array& array ) +{ + const typename MT::ResultType tmp( ~array ); + return tmp; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checks if the given array is empty. +// \ingroup array +// +// \param array The array to be checked. +// \return \a true if the array is empty, \a false if not. +// +// This function checks if the total number of elements of the given array is zero. If the +// total number of elements is zero the function returns \a true, otherwise it returns \a false. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE constexpr bool isEmpty( const Array& array ) noexcept +{ + return size( ~array ) == 0UL; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checks if the given array is a square array. +// \ingroup array +// +// \param array The array to be checked. +// \return \a true if the array is a square array, \a false if not. +// +// This function checks if the number of rows and columns of the given array are equal. If +// they are, the function returns \a true, otherwise it returns \a false. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE bool isSquare( const Array& array ) noexcept +{ + return ( IsSquare_v || ( (~array).rows() == (~array).columns() && (~array).rows() == (~array).pages() ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the two given arrays represent the same observable state. +// \ingroup array +// +// \param a The first array to be tested for its state. +// \param b The second array to be tested for its state. +// \return \a true in case the two arrays share a state, \a false otherwise. +// +// The isSame function provides an abstract interface for testing if the two given arrays +// represent the same observable state. This happens for instance in case \c a and \c b refer +// to the same array or in case \c a and \c b are aliases for the same array. In case both +// arrays represent the same observable state, the function returns \a true, other it returns +// \a false. + + \code + blaze::DynamicArray mat1( 4UL, 5UL ); // Setup of a 4x5 dynamic array + blaze::DynamicArray mat2( 4UL, 5UL ); // Setup of a second 4x5 dynamic array + + auto sub1 = subarray( mat1, 4UL, 0UL, 0UL, 5UL ); // Subarray fully covering mat1 + auto sub2 = subarray( mat1, 2UL, 1UL, 1UL, 3UL ); // Subarray partially covering mat1 + auto sub3 = subarray( mat1, 2UL, 1UL, 1UL, 3UL ); // Subarray partially covering mat1 + + isSame( mat1, mat1 ); // returns true since both objects refer to the same array + isSame( mat1, mat2 ); // returns false since mat1 and mat2 are two different arrays + isSame( mat1, sub1 ); // returns true since sub1 represents the same observable state as mat1 + isSame( mat1, sub3 ); // returns false since sub3 only covers part of mat1 + isSame( sub2, sub3 ); // returns true since sub1 and sub2 refer to exactly the same part of mat1 + isSame( sub1, sub3 ); // returns false since sub1 and sub3 refer to different parts of mat1 + \endcode +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE bool isSame( const Array& a, const Array& b ) noexcept +{ + return ( IsSame_v && + reinterpret_cast( &a ) == reinterpret_cast( &b ) ); +} +//************************************************************************************************* + + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the assignment of two arrays with the same storage order. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be assigned. +// \return void +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void assign_backend( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + (~lhs).assign( ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be assigned. +// \return void +// +// This function implements the default assignment of an array to an array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void assign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" ); + BLAZE_INTERNAL_ASSERT( (~lhs).pages() == (~rhs).pages(), "Invalid number of pages" ); + + assign_backend( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the addition assignment of two arrays with the same +// storage order. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be added. +// \return void +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void addAssign_backend( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + (~lhs).addAssign( ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the addition assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be added. +// \return void +// +// This function implements the default addition assignment of an array to an array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void addAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" ); + BLAZE_INTERNAL_ASSERT( (~lhs).pages() == (~rhs).pages(), "Invalid number of pages" ); + + addAssign_backend( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the subtraction assignment of two arrays with the same +// storage order. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be subtracted. +// \return void +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void subAssign_backend( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + (~lhs).subAssign( ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the subtraction assignment of an array to array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be subtracted. +// \return void +// +// This function implements the default subtraction assignment of an array to an array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void subAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" ); + BLAZE_INTERNAL_ASSERT( (~lhs).pages() == (~rhs).pages(), "Invalid number of pages" ); + + subAssign_backend( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the Schur product assignment of two arrays with the same +// storage order. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array for the Schur product. +// \return void +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void schurAssign_backend( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + (~lhs).schurAssign( ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the Schur product assignment of an array to array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array for the Schur product. +// \return void +// +// This function implements the default Schur product assignment of an array to an array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void schurAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" ); + BLAZE_INTERNAL_ASSERT( (~lhs).pages() == (~rhs).pages(), "Invalid number of pages" ); + + schurAssign_backend( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the multiplication assignment of an array to an array. +// \ingroup array +// +// \param lhs The target left-hand side array. +// \param rhs The right-hand side array to be multiplied. +// \return void +// +// This function implements the default multiplication assignment of an array to an array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side array + , typename TT2 > // Type of the right-hand side array +BLAZE_ALWAYS_INLINE void multAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid array sizes" ); + + (~lhs).multAssign( ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given array. +// \ingroup array +// +// \param array The array to be derestricted. +// \return Reference to the array without access restrictions. +// +// This function removes all restrictions on the data access to the given array. It returns a +// reference to the array that does provide the same interface but does not have any restrictions +// on the data access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE TT& derestrict( Array& array ) +{ + return ~array; +} +/*! \endcond */ +//************************************************************************************************* + + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrDArrMapExpr.h b/blaze_tensor/math/expressions/DArrDArrMapExpr.h new file mode 100644 index 0000000..c747ca4 --- /dev/null +++ b/blaze_tensor/math/expressions/DArrDArrMapExpr.h @@ -0,0 +1,1259 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/expressions/DArrDArrMapExpr.h +// \brief Header file for the dense array/dense array map expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRDARRMAPEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRDARRMAPEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DMATDMATMAPEXPR +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Expression object for the dense array-dense array map() function. +// \ingroup dense_tensor_expression +// +// The DArrDArrMapExpr class represents the compile time expression for the pairwise evaluation +// of a binary custom operation on the elements of two dense tensors with identical storage order +// via the map() function. +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 // Type of the right-hand side dense array + , typename OP > // Type of the custom operation +class DArrDArrMapExpr + : public ArrArrMapExpr< DenseArray< DArrDArrMapExpr > > + , private Computation +{ + private: + //**Type definitions**************************************************************************** + using RT1 = ResultType_t; //!< Result type of the left-hand side dense array expression. + using RT2 = ResultType_t; //!< Result type of the right-hand side dense array expression. + using ET1 = ElementType_t; //!< Element type of the left-hand side dense array expression. + using ET2 = ElementType_t; //!< Element type of the right-hand side dense array expression. + using RN1 = ReturnType_t; //!< Return type of the left-hand side dense array expression. + using RN2 = ReturnType_t; //!< Return type of the right-hand side dense array expression. + using CT1 = CompositeType_t; //!< Composite type of the left-hand side dense array expression. + using CT2 = CompositeType_t; //!< Composite type of the right-hand side dense array expression. + + //! Definition of the HasSIMDEnabled type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled ); + + //! Definition of the HasLoad type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load ); + //********************************************************************************************** + + //**Serial evaluation strategy****************************************************************** + //! Compilation switch for the serial evaluation strategy of the map expression. + /*! The \a useAssign compile time constant expression represents a compilation switch for + the serial evaluation strategy of the map expression. In case either of the two dense + array operands requires an intermediate evaluation, \a useAssign will be set to 1 and + the addition expression will be evaluated via the \a assign function family. Otherwise + \a useAssign will be set to 0 and the expression will be evaluated via the subscript + operator. */ + static constexpr bool useAssign = ( RequiresEvaluation_v || RequiresEvaluation_v ); + + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool UseAssign_v = useAssign; + /*! \endcond */ + //********************************************************************************************** + + //**Parallel evaluation strategy**************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + /*! This variable template is a helper for the selection of the parallel evaluation strategy. + In case at least one of the two dense array operands is not SMP assignable and at least + one of the two operands requires an intermediate evaluation, the variable is set to 1 and + the expression specific evaluation strategy is selected. Otherwise the variable is set to + 0 and the default strategy is chosen. */ + template< typename MT > + static constexpr bool UseSMPAssign_v = + ( ( !MT1::smpAssignable || !MT2::smpAssignable ) && useAssign ); + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + using This = DArrDArrMapExpr; //!< Type of this DArrDArrMapExpr instance. + using ResultType = MapTrait_t; //!< Result type for expression template evaluations. + using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Resulting element type. + + //! Return type for expression template evaluations. + using ReturnType = decltype( std::declval()( std::declval(), std::declval() ) ); + + //! Data type for composite expression templates. + using CompositeType = If_t< useAssign, const ResultType, const DArrDArrMapExpr& >; + + //! Composite type of the left-hand side dense array expression. + using LeftOperand = If_t< IsExpression_v, const MT1, const MT1& >; + + //! Composite type of the right-hand side dense array expression. + using RightOperand = If_t< IsExpression_v, const MT2, const MT2& >; + + //! Data type of the custom unary operation. + using Operation = OP; + + //! Type for the assignment of the left-hand side dense array operand. + using LT = If_t< RequiresEvaluation_v, const RT1, CT1 >; + + //! Type for the assignment of the right-hand side dense array operand. + using RT = If_t< RequiresEvaluation_v, const RT2, CT2 >; + //********************************************************************************************** + + //**ConstIterator class definition************************************************************** + /*!\brief Iterator over the elements of the dense array map expression. + */ + class ConstIterator + { + public: + //**Type definitions************************************************************************* + using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. + using ValueType = ElementType; //!< Type of the underlying elements. + using PointerType = ElementType*; //!< Pointer return type. + using ReferenceType = ElementType&; //!< Reference return type. + using DifferenceType = ptrdiff_t; //!< Difference between two iterators. + + // STL iterator requirements + using iterator_category = IteratorCategory; //!< The iterator category. + using value_type = ValueType; //!< Type of the underlying elements. + using pointer = PointerType; //!< Pointer return type. + using reference = ReferenceType; //!< Reference return type. + using difference_type = DifferenceType; //!< Difference between two iterators. + + //! ConstIterator type of the left-hand side dense array expression. + using LeftIteratorType = ConstIterator_t; + + //! ConstIterator type of the right-hand side dense array expression. + using RightIteratorType = ConstIterator_t; + //******************************************************************************************* + + //**Constructor****************************************************************************** + /*!\brief Constructor for the ConstIterator class. + // + // \param left Iterator to the initial left-hand side element. + // \param right Iterator to the initial right-hand side element. + // \param op The custom unary operation. + */ + explicit inline ConstIterator( LeftIteratorType left, RightIteratorType right, OP op ) + : left_ ( left ) // Iterator to the current left-hand side element + , right_( right ) // Iterator to the current right-hand side element + , op_ ( op ) // The custom unary operation + {} + //******************************************************************************************* + + //**Addition assignment operator************************************************************* + /*!\brief Addition assignment operator. + // + // \param inc The increment of the iterator. + // \return The incremented iterator. + */ + inline ConstIterator& operator+=( size_t inc ) { + left_ += inc; + right_ += inc; + return *this; + } + //******************************************************************************************* + + //**Subtraction assignment operator********************************************************** + /*!\brief Subtraction assignment operator. + // + // \param dec The decrement of the iterator. + // \return The decremented iterator. + */ + inline ConstIterator& operator-=( size_t dec ) { + left_ -= dec; + right_ -= dec; + return *this; + } + //******************************************************************************************* + + //**Prefix increment operator**************************************************************** + /*!\brief Pre-increment operator. + // + // \return Reference to the incremented iterator. + */ + inline ConstIterator& operator++() { + ++left_; + ++right_; + return *this; + } + //******************************************************************************************* + + //**Postfix increment operator*************************************************************** + /*!\brief Post-increment operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator++( int ) { + return ConstIterator( left_++, right_++, op_ ); + } + //******************************************************************************************* + + //**Prefix decrement operator**************************************************************** + /*!\brief Pre-decrement operator. + // + // \return Reference to the decremented iterator. + */ + inline ConstIterator& operator--() { + --left_; + --right_; + return *this; + } + //******************************************************************************************* + + //**Postfix decrement operator*************************************************************** + /*!\brief Post-decrement operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator--( int ) { + return ConstIterator( left_--, right_--, op_ ); + } + //******************************************************************************************* + + //**Element access operator****************************************************************** + /*!\brief Direct access to the element at the current iterator position. + // + // \return The resulting value. + */ + inline ReturnType operator*() const { + return op_( *left_, *right_ ); + } + //******************************************************************************************* + + //**Load function**************************************************************************** + /*!\brief Access to the SIMD elements of the array. + // + // \return The resulting SIMD element. + */ + inline auto load() const noexcept { + return op_.load( left_.load(), right_.load() ); + } + //******************************************************************************************* + + //**Equality operator************************************************************************ + /*!\brief Equality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators refer to the same element, \a false if not. + */ + inline bool operator==( const ConstIterator& rhs ) const { + return left_ == rhs.left_; + } + //******************************************************************************************* + + //**Inequality operator********************************************************************** + /*!\brief Inequality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators don't refer to the same element, \a false if they do. + */ + inline bool operator!=( const ConstIterator& rhs ) const { + return left_ != rhs.left_; + } + //******************************************************************************************* + + //**Less-than operator*********************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller, \a false if not. + */ + inline bool operator<( const ConstIterator& rhs ) const { + return left_ < rhs.left_; + } + //******************************************************************************************* + + //**Greater-than operator******************************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater, \a false if not. + */ + inline bool operator>( const ConstIterator& rhs ) const { + return left_ > rhs.left_; + } + //******************************************************************************************* + + //**Less-or-equal-than operator************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. + */ + inline bool operator<=( const ConstIterator& rhs ) const { + return left_ <= rhs.left_; + } + //******************************************************************************************* + + //**Greater-or-equal-than operator*********************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater or equal, \a false if not. + */ + inline bool operator>=( const ConstIterator& rhs ) const { + return left_ >= rhs.left_; + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Calculating the number of elements between two iterators. + // + // \param rhs The right-hand side iterator. + // \return The number of elements between the two iterators. + */ + inline DifferenceType operator-( const ConstIterator& rhs ) const { + return left_ - rhs.left_; + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between a ConstIterator and an integral value. + // + // \param it The iterator to be incremented. + // \param inc The number of elements the iterator is incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { + return ConstIterator( it.left_ + inc, it.right_ + inc, it.op_ ); + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between an integral value and a ConstIterator. + // + // \param inc The number of elements the iterator is incremented. + // \param it The iterator to be incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { + return ConstIterator( it.left_ + inc, it.right_ + inc, it.op_ ); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Subtraction between a ConstIterator and an integral value. + // + // \param it The iterator to be decremented. + // \param dec The number of elements the iterator is decremented. + // \return The decremented iterator. + */ + friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { + return ConstIterator( it.left_ - dec, it.right_ - dec, it.op_ ); + } + //******************************************************************************************* + + private: + //**Member variables************************************************************************* + LeftIteratorType left_; //!< Iterator to the current left-hand side element. + RightIteratorType right_; //!< Iterator to the current right-hand side element. + OP op_; //!< The custom unary operation. + //******************************************************************************************* + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = + ( MT1::simdEnabled && MT2::simdEnabled && + If_t< HasSIMDEnabled_v, GetSIMDEnabled, HasLoad >::value ); + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = ( MT1::smpAssignable && MT2::smpAssignable ); + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + //**Constructor********************************************************************************* + /*!\brief Constructor for the DArrDArrMapExpr class. + // + // \param lhs The left-hand side dense array operand of the map expression. + // \param rhs The right-hand side dense array operand of the map expression. + // \param op The custom unary operation. + */ + explicit inline DArrDArrMapExpr( const MT1& lhs, const MT2& rhs, OP op ) noexcept + : lhs_( lhs ) // Left-hand side dense array of the map expression + , rhs_( rhs ) // Right-hand side dense array of the map expression + , op_ ( op ) // The custom unary operation + {} + //********************************************************************************************** + + //**Access operator***************************************************************************** + /*!\brief 2D-access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + */ + template< typename... Dims > + inline ReturnType operator()( Dims... dims ) const { + return op_( lhs_(dims...), rhs_(dims...) ); + } + //********************************************************************************************** + + //**At function********************************************************************************* + /*!\brief Checked access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + // \exception std::out_of_range Invalid array access index. + */ + template< typename... Dims > + inline ReturnType at( Dims... dims ) const { + constexpr size_t indices[] = {dims...}; + + ArrayDimForEach( dims_, [&]( size_t i ) { + if( indices[i] >= dims_[i + 1] ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + return (*this)(dims...); + } + //********************************************************************************************** + + //**Load function******************************************************************************* + /*!\brief Access to the SIMD elements of the array. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return Reference to the accessed values. + */ + template< typename... Dims > + BLAZE_ALWAYS_INLINE auto load( Dims... dims ) const noexcept { + return op_.load( lhs_.load(dims...), rhs_.load(dims...) ); + } + //********************************************************************************************** + + //**Begin function****************************************************************************** + /*!\brief Returns an iterator to the first non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator to the first non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator begin( size_t i, Dims... dims ) const { + return ConstIterator( lhs_.begin(i, dims...), rhs_.begin(i, dims...), op_ ); + } + //********************************************************************************************** + + //**End function******************************************************************************** + /*!\brief Returns an iterator just past the last non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator just past the last non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator end( size_t i, Dims... dims ) const { + return ConstIterator( lhs_.end(i, dims...), rhs_.end(i, dims...), op_ ); + } + //********************************************************************************************** + + //**Rows function******************************************************************************* + /*!\brief Returns the current number of elements of the array. + // + // \return The number of rows of the array. + */ + inline constexpr size_t num_dimensions() const noexcept { + return lhs_.num_dimensions(); + } + //********************************************************************************************** + + //**Columns function**************************************************************************** + /*!\brief Returns the current number of elements in the given dimension of the array. + // + // \return The number of elements in the given dimension of the array. + */ + template < size_t Dim > + inline size_t dimension() const noexcept { + return lhs_.template dimension(); + } + //********************************************************************************************** + + //**Right operand access************************************************************************ + /*!\brief Returns the right-hand side dense array operand. + // + // \return The right-hand side dense array operand. + */ + inline RightOperand rightOperand() const noexcept { + return rhs_; + } + //********************************************************************************************** + + //**Operation access**************************************************************************** + /*!\brief Returns a copy of the custom operation. + // + // \return A copy of the custom operation. + */ + inline Operation operation() const { + return op_; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can alias with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case the expression can alias, \a false otherwise. + */ + template< typename T > + inline bool canAlias( const T* alias ) const noexcept { + return ( IsExpression_v && lhs_.canAlias( alias ) ) || + ( IsExpression_v && rhs_.canAlias( alias ) ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression is aliased with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case an alias effect is detected, \a false otherwise. + */ + template< typename T > + inline bool isAliased( const T* alias ) const noexcept { + return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the operands of the expression are properly aligned in memory. + // + // \return \a true in case the operands are aligned, \a false if not. + */ + inline bool isAligned() const noexcept { + return lhs_.isAligned() && rhs_.isAligned(); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can be used in SMP assignments. + // + // \return \a true in case the expression can be used in SMP assignments, \a false if not. + */ + inline bool canSMPAssign() const noexcept { + return lhs_.canSMPAssign() && rhs_.canSMPAssign(); + } + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + LeftOperand lhs_; //!< Left-hand side dense array of the map expression. + RightOperand rhs_; //!< Right-hand side dense array of the map expression. + Operation op_; //!< The custom unary operation. + //********************************************************************************************** + + //**Assignment to dense tensors**************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a dense array-dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a dense array-dense + // array map expression to a dense array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case either of the two + // operands requires an intermediate evaluation. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + assign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense array operand + RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + assign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to dense tensors******************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief Addition assignment of a dense array-dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be added. + // \return void + // + // This function implements the performance optimized addition assignment of a dense + // array-dense array map expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case + // either of the two operands requires an intermediate evaluation. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + addAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense array operand + RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + addAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Subtraction assignment to dense tensors**************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Subtraction assignment of a dense array-dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be subtracted. + // \return void + // + // This function implements the performance optimized subtraction assignment of a dense + // array-dense array map expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case + // either of the two operands requires an intermediate evaluation. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + subAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense array operand + RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + subAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Schur product assignment to dense tensors************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Schur product assignment of a dense array-dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression for the Schur product. + // \return void + // + // This function implements the performance optimized Schur product assignment of a dense + // array-dense array map expression to a dense array. Due to the explicit application of + // the SFINAE principle, this function can only be selected by the compiler in case either + // of the two operands requires an intermediate evaluation. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + schurAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense array operand + RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + schurAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to dense tensors************************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a dense array-dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a dense array-dense + // array map expression to a dense array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression + // specific parallel evaluation strategy is selected. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense array operand + RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + smpAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP addition assignment to dense tensors*************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP addition assignment of a dense array-dense array map expression to a dense + // array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be added. + // \return void + // + // This function implements the performance optimized SMP addition assignment of a dense + // array-dense array map expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAddAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense array operand + RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + smpAddAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP subtraction assignment to dense tensors************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP subtraction assignment of a dense array-dense array map expression to a dense + // array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be subtracted. + // \return void + // + // This function implements the performance optimized SMP subtraction assignment of a dense + // array-dense array map expression to a dense array. Due to the explicit application of + // the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSubAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense array operand + RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + smpSubAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP Schur product assignment to dense tensors********************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP Schur product assignment of a dense array-dense array map expression to a + // dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression for the Schur product. + // \return void + // + // This function implements the performance optimized SMP Schur product assignment of a + // dense array-dense array map expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename MT > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSchurAssign( DenseArray& lhs, const DArrDArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs_).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense array operand + RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense array operand + + BLAZE_INTERNAL_ASSERT( A.dimensions() == rhs.lhs_.dimensions(), "Invalid number of elements" ); + BLAZE_INTERNAL_ASSERT( B.dimensions() == rhs.rhs_.dimensions(), "Invalid number of elements" ); + + smpSchurAssign( ~lhs, map( A, B, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT2 ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Evaluates the given binary operation on each single element of the dense tensors +// \a lhs and \a rhs. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array operand. +// \param rhs The right-hand side dense array operand. +// \param op The custom, binary operation. +// \return The binary operation applied to each single element of \a lhs and \a rhs. +// \exception std::invalid_argument Array sizes do not match. +// +// The \a map() function evaluates the given binary operation on each element of the input +// tensors \a lhs and \a rhs. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a map() function: + + \code + blaze::DynamicArray A, B, C; + // ... Resizing and initialization + C = map( A, B, []( double x, double y ){ return std::min( x, y ); } ); + \endcode +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 // Type of the right-hand side dense array + , typename OP > // Type of the custom operation +inline decltype(auto) + map( const DenseArray& lhs, const DenseArray& rhs, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).dimensions() != (~rhs).dimensions() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using ReturnType = const DArrDArrMapExpr; + return ReturnType( ~lhs, ~rhs, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the componentwise minimum of the dense tensors \a lhs and \a rhs. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array operand. +// \param rhs The right-hand side dense array operand. +// \return The resulting dense array. +// +// This function computes the componentwise minimum of the two dense tensors \a lhs and \a rhs. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a min() function: + + \code + blaze::DynamicArray A, B, C; + // ... Resizing and initialization + C = min( A, B ); + \endcode +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline decltype(auto) + min( const DenseArray& lhs, const DenseArray& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return map( ~lhs, ~rhs, Min() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the componentwise maximum of the dense tensors \a lhs and \a rhs. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array operand. +// \param rhs The right-hand side dense array operand. +// \return The resulting dense array. +// +// This function computes the componentwise maximum of the two dense tensors \a lhs and \a rhs. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a max() function: + + \code + blaze::DynamicArray A, B, C; + // ... Resizing and initialization + C = max( A, B ); + \endcode +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline decltype(auto) + max( const DenseArray& lhs, const DenseArray& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return map( ~lhs, ~rhs, Max() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the componentwise hypotenous for the dense tensors \a lhs and \a rhs. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array operand. +// \param rhs The right-hand side dense array operand. +// \return The resulting dense array. +// +// The \a hypot() function computes the componentwise hypotenous for the two dense tensors +// \a lhs and \a rhs. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a hypot() function: + + \code + blaze::DynamicArray A, B, C; + // ... Resizing and initialization + C = hypot( A, B ); + \endcode +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline decltype(auto) + hypot( const DenseArray& lhs, const DenseArray& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return map( ~lhs, ~rhs, Hypot() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the componentwise exponential value for the dense tensors \a lhs and \a rhs. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array operand. +// \param rhs The right-hand side dense array operand. +// \return The resulting dense array. +// +// The \a pow() function computes the componentwise exponential value for the two dense tensors +// \a lhs and \a rhs. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a pow() function: + + \code + blaze::DynamicArray A, B, C; + // ... Resizing and initialization + C = pow( A, B ); + \endcode +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline decltype(auto) + pow( const DenseArray& lhs, const DenseArray& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return map( ~lhs, ~rhs, Pow() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the multi-valued inverse tangent of the dense tensors \a lhs and \a rhs. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array operand. +// \param rhs The right-hand side dense array operand. +// \return The resulting dense array. +// +// This function computes the multi-valued inverse tangent of the two dense array \a lhs and +// \a rhs. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a max() function: + + \code + blaze::DynamicArray A, B, C; + // ... Resizing and initialization + C = atan2( A, B ); + \endcode +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline decltype(auto) + atan2( const DenseArray& lhs, const DenseArray& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return map( ~lhs, ~rhs, Atan2() ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsAligned< DArrDArrMapExpr > + : public BoolConstant< IsAligned_v && IsAligned_v > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsPadded< DArrDArrMapExpr > + : public BoolConstant< IsPadded_v && IsPadded_v > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsSymmetric< DArrDArrMapExpr > + : public YieldsSymmetric +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsHermitian< DArrDArrMapExpr > + : public YieldsHermitian +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsLower< DArrDArrMapExpr > + : public YieldsLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsUniLower< DArrDArrMapExpr > + : public YieldsUniLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsStrictlyLower< DArrDArrMapExpr > + : public YieldsStrictlyLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsUpper< DArrDArrMapExpr > + : public YieldsUpper +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsUniUpper< DArrDArrMapExpr > + : public YieldsUniUpper +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename OP > +struct IsStrictlyUpper< DArrDArrMapExpr > + : public YieldsStrictlyUpper +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrMapExpr.h b/blaze_tensor/math/expressions/DArrMapExpr.h new file mode 100644 index 0000000..85078d8 --- /dev/null +++ b/blaze_tensor/math/expressions/DArrMapExpr.h @@ -0,0 +1,2433 @@ +//================================================================================================= +/*! +// \file blaze/math/expressions/DArrMapExpr.h +// \brief Header file for the dense array map expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRMAPEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRMAPEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DTENSMAPEXPR +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Expression object for the dense array map() function. +// \ingroup dense_array_expression +// +// The DArrMapExpr class represents the compile time expression for the evaluation of a custom +// operation on each element of a dense array via the map() function. +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the custom operation +class DArrMapExpr + : public ArrMapExpr< DenseArray< DArrMapExpr > > + , private Computation +{ + private: + //**Type definitions**************************************************************************** + using RT = ResultType_t; //!< Result type of the dense array expression. + using OT = OppositeType_t; //!< Opposite type of the dense array expression. + using ET = ElementType_t; //!< Element type of the dense array expression. + using RN = ReturnType_t; //!< Return type of the dense array expression. + + //! Definition of the HasSIMDEnabled type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled ); + + //! Definition of the HasLoad type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load ); + //********************************************************************************************** + + //**Serial evaluation strategy****************************************************************** + //! Compilation switch for the serial evaluation strategy of the map expression. + /*! The \a useAssign compile time constant expression represents a compilation switch for + the serial evaluation strategy of the map expression. In case the given dense array + expression of type \a MT requires an intermediate evaluation, \a useAssign will be + set to 1 and the map expression will be evaluated via the \a assign function family. + Otherwise \a useAssign will be set to 0 and the expression will be evaluated via the + subscript operator. */ + static constexpr bool useAssign = RequiresEvaluation_v; + + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool UseAssign_v = useAssign; + /*! \endcond */ + //********************************************************************************************** + + //**Parallel evaluation strategy**************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + /*! This variable template is a helper for the selection of the parallel evaluation strategy. + In case either the target array or the dense array operand is not SMP assignable and + the array operand requires an intermediate evaluation, the variable is set to 1 and the + expression specific evaluation strategy is selected. Otherwise the variable is set to 0 + and the default strategy is chosen. */ + template< typename MT2 > + static constexpr bool UseSMPAssign_v = + ( ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign ); + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + using This = DArrMapExpr; //!< Type of this DArrMapExpr instance. + using ResultType = MapTrait_t; //!< Result type for expression template evaluations. + using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Resulting element type. + + //! Return type for expression template evaluations. + using ReturnType = decltype( std::declval()( std::declval() ) ); + + //! Data type for composite expression templates. + using CompositeType = If_t< useAssign, const ResultType, const DArrMapExpr& >; + + //! Composite data type of the dense array expression. + using Operand = If_t< IsExpression_v, const MT, const MT& >; + + //! Data type of the custom unary operation. + using Operation = OP; + //********************************************************************************************** + + //**ConstIterator class definition************************************************************** + /*!\brief Iterator over the elements of the dense array map expression. + */ + class ConstIterator + { + public: + //**Type definitions************************************************************************* + using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. + using ValueType = ElementType; //!< Type of the underlying elements. + using PointerType = ElementType*; //!< Pointer return type. + using ReferenceType = ElementType&; //!< Reference return type. + using DifferenceType = ptrdiff_t; //!< Difference between two iterators. + + // STL iterator requirements + using iterator_category = IteratorCategory; //!< The iterator category. + using value_type = ValueType; //!< Type of the underlying elements. + using pointer = PointerType; //!< Pointer return type. + using reference = ReferenceType; //!< Reference return type. + using difference_type = DifferenceType; //!< Difference between two iterators. + + //! ConstIterator type of the dense array expression. + using IteratorType = ConstIterator_t; + //******************************************************************************************* + + //**Constructor****************************************************************************** + /*!\brief Constructor for the ConstIterator class. + // + // \param it Iterator to the initial array element. + // \param op The custom unary operation. + */ + explicit inline ConstIterator( IteratorType it, OP op ) + : it_( it ) // Iterator to the current array element + , op_( op ) // The custom unary operation + {} + //******************************************************************************************* + + //**Addition assignment operator************************************************************* + /*!\brief Addition assignment operator. + // + // \param inc The increment of the iterator. + // \return The incremented iterator. + */ + inline ConstIterator& operator+=( size_t inc ) { + it_ += inc; + return *this; + } + //******************************************************************************************* + + //**Subtraction assignment operator********************************************************** + /*!\brief Subtraction assignment operator. + // + // \param dec The decrement of the iterator. + // \return The decremented iterator. + */ + inline ConstIterator& operator-=( size_t dec ) { + it_ -= dec; + return *this; + } + //******************************************************************************************* + + //**Prefix increment operator**************************************************************** + /*!\brief Pre-increment operator. + // + // \return Reference to the incremented iterator. + */ + inline ConstIterator& operator++() { + ++it_; + return *this; + } + //******************************************************************************************* + + //**Postfix increment operator*************************************************************** + /*!\brief Post-increment operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator++( int ) { + return ConstIterator( it_++, op_ ); + } + //******************************************************************************************* + + //**Prefix decrement operator**************************************************************** + /*!\brief Pre-decrement operator. + // + // \return Reference to the decremented iterator. + */ + inline ConstIterator& operator--() { + --it_; + return *this; + } + //******************************************************************************************* + + //**Postfix decrement operator*************************************************************** + /*!\brief Post-decrement operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator--( int ) { + return ConstIterator( it_--, op_ ); + } + //******************************************************************************************* + + //**Element access operator****************************************************************** + /*!\brief Direct access to the element at the current iterator position. + // + // \return The resulting value. + */ + inline ReturnType operator*() const { + return op_( *it_ ); + } + //******************************************************************************************* + + //**Load function**************************************************************************** + /*!\brief Access to the SIMD elements of the array. + // + // \return The resulting SIMD element. + */ + inline auto load() const noexcept { + return op_.load( it_.load() ); + } + //******************************************************************************************* + + //**Equality operator************************************************************************ + /*!\brief Equality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators refer to the same element, \a false if not. + */ + inline bool operator==( const ConstIterator& rhs ) const { + return it_ == rhs.it_; + } + //******************************************************************************************* + + //**Inequality operator********************************************************************** + /*!\brief Inequality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators don't refer to the same element, \a false if they do. + */ + inline bool operator!=( const ConstIterator& rhs ) const { + return it_ != rhs.it_; + } + //******************************************************************************************* + + //**Less-than operator*********************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller, \a false if not. + */ + inline bool operator<( const ConstIterator& rhs ) const { + return it_ < rhs.it_; + } + //******************************************************************************************* + + //**Greater-than operator******************************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater, \a false if not. + */ + inline bool operator>( const ConstIterator& rhs ) const { + return it_ > rhs.it_; + } + //******************************************************************************************* + + //**Less-or-equal-than operator************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. + */ + inline bool operator<=( const ConstIterator& rhs ) const { + return it_ <= rhs.it_; + } + //******************************************************************************************* + + //**Greater-or-equal-than operator*********************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater or equal, \a false if not. + */ + inline bool operator>=( const ConstIterator& rhs ) const { + return it_ >= rhs.it_; + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Calculating the number of elements between two iterators. + // + // \param rhs The right-hand side iterator. + // \return The number of elements between the two iterators. + */ + inline DifferenceType operator-( const ConstIterator& rhs ) const { + return it_ - rhs.it_; + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between a ConstIterator and an integral value. + // + // \param it The iterator to be incremented. + // \param inc The number of elements the iterator is incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { + return ConstIterator( it.it_ + inc, it.op_ ); + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between an integral value and a ConstIterator. + // + // \param inc The number of elements the iterator is incremented. + // \param it The iterator to be incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { + return ConstIterator( it.it_ + inc, it.op_ ); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Subtraction between a ConstIterator and an integral value. + // + // \param it The iterator to be decremented. + // \param dec The number of elements the iterator is decremented. + // \return The decremented iterator. + */ + friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { + return ConstIterator( it.it_ - dec, it.op_ ); + } + //******************************************************************************************* + + private: + //**Member variables************************************************************************* + IteratorType it_; //!< Iterator to the current array element. + OP op_; //!< The custom unary operation. + //******************************************************************************************* + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = + ( MT::simdEnabled && + If_t< HasSIMDEnabled_v, GetSIMDEnabled, HasLoad >::value ); + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = MT::smpAssignable; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + //**Constructor********************************************************************************* + /*!\brief Constructor for the DArrMapExpr class. + // + // \param dm The dense array operand of the map expression. + // \param op The custom unary operation. + */ + explicit inline DArrMapExpr( const MT& dm, OP op ) noexcept + : dm_( dm ) // Dense array of the map expression + , op_( op ) // The custom unary operation + {} + //********************************************************************************************** + + //**Access operator***************************************************************************** + /*!\brief 2D-access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + */ + template< typename... Dims > + inline ReturnType operator()( Dims... dims ) const noexcept + { + return op_( dm_( dims... ) ); + } + //********************************************************************************************** + + //**At function********************************************************************************* + /*!\brief Checked access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + // \exception std::out_of_range Invalid array access index. + */ + template< typename... Dims > + inline ReturnType at( Dims... dims ) const { + return ( *this )( dims... ); + } + //********************************************************************************************** + + //**Load function******************************************************************************* + /*!\brief Access to the SIMD elements of the array. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return Reference to the accessed values. + */ + template< typename... Dims > + BLAZE_ALWAYS_INLINE auto load( Dims... dims ) const noexcept { + return op_.load( dm_.load( dims... ) ); + } + //********************************************************************************************** + + //**Begin function****************************************************************************** + /*!\brief Returns an iterator to the first non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator to the first non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator begin( size_t i, Dims... dims ) const { + return ConstIterator( dm_.begin(i, dims...), op_ ); + } + //********************************************************************************************** + + //**End function******************************************************************************** + /*!\brief Returns an iterator just past the last non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator just past the last non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator end( size_t i, Dims... dims ) const { + return ConstIterator( dm_.end(i, dims...), op_ ); + } + //********************************************************************************************** + + //**Num_dimensions function******************************************************************************* + /*!\brief Returns the current number of dimensions of the array. + // + // \return The number of rows of the array. + */ + inline static constexpr size_t num_dimensions() noexcept { + return RemoveCV_t>::num_dimensions(); + } + //********************************************************************************************** + + //**Dimensions function**************************************************************************** + /*!\brief Returns the current dimensions of the array. + // + // \return The dimensions of the array. + */ + inline decltype(auto) dimensions() const noexcept { + return dm_.dimensions(); + } + //********************************************************************************************** + + //**Dimension function**************************************************************************** + /*!\brief Returns the current number of columns of the array. + // + // \return The number of columns of the array. + */ + template< size_t Dim > + inline size_t dimension() const noexcept { + return dm_.template dimension(); + } + //********************************************************************************************** + + //**Operand access****************************************************************************** + /*!\brief Returns the dense array operand. + // + // \return The dense array operand. + */ + inline Operand operand() const noexcept { + return dm_; + } + //********************************************************************************************** + + //**Operation access**************************************************************************** + /*!\brief Returns a copy of the custom operation. + // + // \return A copy of the custom operation. + */ + inline Operation operation() const { + return op_; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can alias with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case the expression can alias, \a false otherwise. + */ + template< typename T > + inline bool canAlias( const T* alias ) const noexcept { + return IsExpression_v && dm_.canAlias( alias ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression is aliased with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case an alias effect is detected, \a false otherwise. + */ + template< typename T > + inline bool isAliased( const T* alias ) const noexcept { + return dm_.isAliased( alias ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the operands of the expression are properly aligned in memory. + // + // \return \a true in case the operands are aligned, \a false if not. + */ + inline bool isAligned() const noexcept { + return dm_.isAligned(); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can be used in SMP assignments. + // + // \return \a true in case the expression can be used in SMP assignments, \a false if not. + */ + inline bool canSMPAssign() const noexcept { + return dm_.canSMPAssign(); + } + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + Operand dm_; //!< Dense array of the map expression. + Operation op_; //!< The custom unary operation. + //********************************************************************************************** + + //**Assignment to dense arrays**************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a dense array map + // expression to a dense array. Due to the explicit application of the SFINAE principle, + // this function can only be selected by the compiler in case the operand requires an + // intermediate evaluation and the underlying numeric data type of the operand and the + // target array are identical. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v && IsSame_v< UnderlyingNumeric_t + , UnderlyingNumeric_t > > + assign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + assign( ~lhs, rhs.dm_ ); + assign( ~lhs, rhs.op_( ~lhs ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Assignment to dense arrays**************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a dense array map + // expression to a dense array. Due to the explicit application of the SFINAE principle, + // this function can only be selected by the compiler in case the operand requires an + // intermediate evaluation and the underlying numeric data type of the operand and the + // target vector differ. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v && !IsSame_v< UnderlyingNumeric_t + , UnderlyingNumeric_t > > + assign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); + assign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to dense arrays******************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief Addition assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be added. + // \return void + // + // This function implements the performance optimized addition assignment of a dense + // array map expression to a dense array. Due to the explicit application of the + // SFINAE principle, this operator can only be selected by the compiler in case the + // operand requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + addAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); + addAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Subtraction assignment to dense arrays**************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Subtraction assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be subtracted. + // \return void + // + // This function implements the performance optimized subtraction assignment of a dense + // array map expression to a dense array. Due to the explicit application of the SFINAE + // principle, this operator can only be selected by the compiler in case the operand + // requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + subAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); + subAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Schur product assignment to dense arrays************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Schur product assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression for the Schur product. + // \return void + // + // This function implements the performance optimized Schur product assignment of a dense + // array map expression to a dense array. Due to the explicit application of the SFINAE + // principle, this operator can only be selected by the compiler in case the operand + // requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + schurAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); + schurAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to dense arrays************************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a dense array map expression to a row-major dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a dense array + // map expression to a row-major dense array. Due to the explicit application of the + // SFINAE principle, this operator can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected and the underlying + // numeric data type of the operand and the target array are identical. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v && IsSame_v< UnderlyingNumeric_t + , UnderlyingNumeric_t > > + smpAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + smpAssign( ~lhs, rhs.dm_ ); + smpAssign( ~lhs, rhs.op_( ~lhs ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to dense arrays************************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a dense array map expression to a row-major dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a dense array map + // expression to a row-major dense array. Due to the explicit application of the SFINAE + // principle, this operator can only be selected by the compiler in case the expression + // specific parallel evaluation strategy is selected and the underlying numeric data type + // of the operand and the target vector differ. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v && !IsSame_v< UnderlyingNumeric_t + , UnderlyingNumeric_t > > + smpAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); + smpAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP addition assignment to dense arrays*************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP addition assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be added. + // \return void + // + // This function implements the performance optimized SMP addition assignment of a dense + // array map expression to a dense array. Due to the explicit application of the SFINAE + // principle, this operator can only be selected by the compiler in case the expression + // specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAddAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); + smpAddAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP subtraction assignment to dense arrays************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP subtraction assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression to be subtracted. + // \return void + // + // This function implements the performance optimized SMP subtraction assignment of a + // dense array map expression to a dense array. Due to the explicit application of + // the SFINAE principle, this operator can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSubAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); + smpSubAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP Schur product assignment to dense arrays********************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP Schur product assignment of a dense array map expression to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side map expression for the Schur product. + // \return void + // + // This function implements the performance optimized SMP Schur product assignment of a + // dense array map expression to a dense array. Due to the explicit application of the + // SFINAE principle, this operator can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSchurAssign( DenseArray& lhs, const DArrMapExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RT ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RT ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); + smpSchurAssign( ~lhs, map( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Evaluates the given custom operation on each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \param op The custom operation. +// \return The custom operation applied to each single element of \a dm. +// +// The \a map() function evaluates the given custom operation on each element of the input +// array \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a map() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = map( A, []( double a ){ return std::sqrt( a ); } ); + \endcode +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the custom operation +inline decltype(auto) map( const DenseArray& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Evaluates the given custom operation on each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \param op The custom operation. +// \return The custom operation applied to each single element of \a dm. +// +// The \a forEach() function evaluates the given custom operation on each element of the input +// array \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a forEach() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = forEach( A, []( double a ){ return std::sqrt( a ); } ); + \endcode +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the custom operation +inline decltype(auto) forEach( const DenseArray& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Applies the \a abs() function to each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// This function applies the \a abs() function to each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a abs() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = abs( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) abs( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Abs() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Applies the \a sign() function to each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// This function applies the \a sign() function to each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a sign() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = sign( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sign( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Sign() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Applies the \a floor() function to each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// This function applies the \a floor() function to each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a floor() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = floor( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) floor( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Floor() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Applies the \a ceil() function to each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// This function applies the \a ceil() function to each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a ceil() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = ceil( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) ceil( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Ceil() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Applies the \a trunc() function to each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// This function applies the \a trunc() function to each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a trunc() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = trunc( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) trunc( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Trunc() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Applies the \a round() function to each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// This function applies the \a round() function to each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a round() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = round( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) round( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Round() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns a array containing the complex conjugate of each single element of \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The conjugate complex of each single element of \a dm. +// +// The \a conj function calculates the complex conjugate of each element of the input array +// \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a conj function: + + \code + blaze::DynamicArray< complex > A, B; + // ... Resizing and initialization + B = conj( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) conj( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Conj() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the conjugate transpose array of \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The conjugate transpose of \a dm. +// +// The \a ctrans function returns an expression representing the conjugate transpose (also called +// adjoint array, Hermitian conjugate array or transjugate array) of the given input array +// \a dm.\n +// The following example demonstrates the use of the \a ctrans function: + + \code + blaze::DynamicArray< complex > A, B; + // ... Resizing and initialization + B = ctrans( A ); + \endcode + +// Note that the \a ctrans function has the same effect as manually applying the \a conj and +// \a trans function in any order: + + \code + B = trans( conj( A ) ); // Computing the conjugate transpose array + B = conj( trans( A ) ); // Computing the conjugate transpose array + \endcode +*/ +template< typename MT // Type of the dense array + , typename ... RTAs> // Runtime arguments +inline decltype(auto) ctrans( const DenseArray& dm, RTAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return trans( conj( ~dm ), args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns a array containing the real part of each single element of \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The real part of each single element of \a dm. +// +// The \a real function calculates the real part of each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a real function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = real( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) real( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Real() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns a array containing the imaginary part of each single element of \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The imaginary part of each single element of \a dm. +// +// The \a imag function calculates the imaginary part of each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a imag function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = imag( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) imag( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Imag() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the square root of each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[0..\infty)\f$. +// \return The square root of each single element of \a dm. +// +// The \a sqrt() function computes the square root of each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a sqrt() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = sqrt( A ); + \endcode + +// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sqrt( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Sqrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse square root of each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$(0..\infty)\f$. +// \return The inverse square root of each single element of \a dm. +// +// The \a invsqrt() function computes the inverse square root of each element of the input array +// \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a invsqrt() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = invsqrt( A ); + \endcode + +// \note All elements are expected to be in the range \f$(0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) invsqrt( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, InvSqrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the cubic root of each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[0..\infty)\f$. +// \return The cubic root of each single element of \a dm. +// +// The \a cbrt() function computes the cubic root of each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a cbrt() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = cbrt( A ); + \endcode + +// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) cbrt( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Cbrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse cubic root of each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$(0..\infty)\f$. +// \return The inverse cubic root of each single element of \a dm. +// +// The \a invcbrt() function computes the inverse cubic root of each element of the input array +// \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a invcbrt() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = invcbrt( A ); + \endcode + +// \note All elements are expected to be in the range \f$(0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) invcbrt( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, InvCbrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Restricts each single element of the dense array \a dm to the range \f$[min..max]\f$. +// \ingroup dense_array +// +// \param dm The input array. +// \param min The lower delimiter. +// \param max The upper delimiter. +// \return The array with restricted elements. +// +// The \a clamp() function restricts each element of the input array \a dm to the range +// \f$[min..max]\f$. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a clamp() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = clamp( A, -1.0, 1.0 ); + \endcode +*/ +template< typename MT // Type of the dense array + , typename DT > // Type of the delimiters +inline decltype(auto) clamp( const DenseArray& dm, const DT& min, const DT& max ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr>; + return ReturnType( ~dm, Clamp
( min, max ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the exponential value for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \param exp The scalar exponent. +// \return The exponential value of each single element of \a dm. +// +// The \a pow() function computes the exponential value for each element of the input array +// \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a pow() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = pow( A, 4.2 ); + \endcode +*/ +template< typename MT // Type of the dense array + , typename ST // Type of the scalar exponent + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) pow( const DenseArray& dm, ST exp ) +{ + BLAZE_FUNCTION_TRACE; + + using ScalarType = MultTrait_t< UnderlyingBuiltin_t, ST >; + using ReturnType = const DArrMapExpr>; + return ReturnType( ~dm, UnaryPow( exp ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes \f$ e^x \f$ for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// The \a exp() function computes \f$ e^x \f$ for each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a exp() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = exp( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) exp( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Exp() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes \f$ 2^x \f$ for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// The \a exp2() function computes \f$ 2^x \f$ for each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a exp2() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = exp2( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) exp2( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Exp2() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes \f$ 10^x \f$ for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The resulting dense array. +// +// The \a exp10() function computes \f$ 10^x \f$ for each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a exp10() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = exp10( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) exp10( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Exp10() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the natural logarithm for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[0..\infty)\f$. +// \return The natural logarithm of each single element of \a dm. +// +// The \a log() function computes natural logarithm for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a log() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = log( A ); + \endcode + +// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) log( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Log() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the binary logarithm for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[0..\infty)\f$. +// \return The binary logarithm of each single element of \a dm. +// +// The \a log2() function computes binary logarithm for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a log2() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = log2( A ); + \endcode + +// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) log2( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Log2() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the common logarithm for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[0..\infty)\f$. +// \return The common logarithm of each single element of \a dm. +// +// The \a log10() function computes common logarithm for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a log10() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = log10( A ); + \endcode + +// \note All elements are expected to be in the range \f$[0..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) log10( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Log10() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the sine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The sine of each single element of \a dm. +// +// The \a sin() function computes the sine for each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a sin() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = sin( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sin( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Sin() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse sine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[-1..1]\f$. +// \return The inverse sine of each single element of \a dm. +// +// The \a asin() function computes the inverse sine for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a asin() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = asin( A ); + \endcode + +// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) asin( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Asin() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the hyperbolic sine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The hyperbolic sine of each single element of \a dm. +// +// The \a sinh() function computes the hyperbolic sine for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a sinh() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = sinh( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sinh( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Sinh() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse hyperbolic sine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The inverse hyperbolic sine of each single element of \a dm. +// +// The \a asinh() function computes the inverse hyperbolic sine for each element of the input +// array \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a asinh() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = asinh( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) asinh( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Asinh() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the cosine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The cosine of each single element of \a dm. +// +// The \a cos() function computes the cosine for each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a cos() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = cos( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) cos( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Cos() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse cosine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[-1..1]\f$. +// \return The inverse cosine of each single element of \a dm. +// +// The \a acos() function computes the inverse cosine for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a acos() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = acos( A ); + \endcode + +// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) acos( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Acos() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the hyperbolic cosine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The hyperbolic cosine of each single element of \a dm. +// +// The \a cosh() function computes the hyperbolic cosine for each element of the input array +// \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a cosh() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = cosh( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) cosh( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Cosh() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse hyperbolic cosine for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[1..\infty)\f$. +// \return The inverse hyperbolic cosine of each single element of \a dm. +// +// The \a acosh() function computes the inverse hyperbolic cosine for each element of the input +// array \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a acosh() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = acosh( A ); + \endcode + +// \note All elements are expected to be in the range \f$[1..\infty)\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) acosh( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Acosh() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the tangent for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The tangent of each single element of \a dm. +// +// The \a tan() function computes the tangent for each element of the input array \a dm. The +// function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a tan() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = tan( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) tan( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Tan() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse tangent for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The inverse tangent of each single element of \a dm. +// +// The \a atan() function computes the inverse tangent for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a atan() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = atan( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) atan( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Atan() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the hyperbolic tangent for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[-1..1]\f$. +// \return The hyperbolic tangent of each single element of \a dm. +// +// The \a tanh() function computes the hyperbolic tangent for each element of the input array +// \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a tanh() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = tanh( A ); + \endcode + +// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) tanh( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Tanh() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the inverse hyperbolic tangent for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array; all elements must be in the range \f$[-1..1]\f$. +// \return The inverse hyperbolic tangent of each single element of \a dm. +// +// The \a atanh() function computes the inverse hyperbolic tangent for each element of the input +// array \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a atanh() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = atanh( A ); + \endcode + +// \note All elements are expected to be in the range \f$[-1..1]\f$. No runtime checks are +// performed to assert this precondition! +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) atanh( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Atanh() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the error function for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The error function of each single element of \a dm. +// +// The \a erf() function computes the error function for each element of the input array \a dm. +// The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a erf() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = erf( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) erf( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Erf() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the complementary error function for each single element of the dense array \a dm. +// \ingroup dense_array +// +// \param dm The input array. +// \return The complementary error function of each single element of \a dm. +// +// The \a erfc() function computes the complementary error function for each element of the input +// array \a dm. The function returns an expression representing this operation.\n +// The following example demonstrates the use of the \a erfc() function: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = erfc( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) erfc( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrMapExpr; + return ReturnType( ~dm, Erfc() ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Absolute value function for dense array absolute value expressions. +// \ingroup dense_array +// +// \param dm The absolute value dense array expression. +// \return The absolute value of each single element of \a dm. +// +// This function implements a performance optimized treatment of the absolute value operation +// on a dense array absolute value expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) abs( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Applies the \a sign() function for dense array \a sign() expressions. +// \ingroup dense_array +// +// \param dm The dense array \a sign() expression. +// \return The sign of each single element of \a dm. +// +// This function implements a performance optimized treatment of the \a sign() operation on a +// dense array \a sign() expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sign( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Applies the \a floor() function to a dense array \a floor() expressions. +// \ingroup dense_array +// +// \param dm The dense array \a floor() expression. +// \return The resulting dense array. +// +// This function implements a performance optimized treatment of the \a floor() operation on +// a dense array \a floor() expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) floor( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Applies the \a ceil() function to a dense array \a ceil() expressions. +// \ingroup dense_array +// +// \param dm The dense array \a ceil() expression. +// \return The resulting dense array. +// +// This function implements a performance optimized treatment of the \a ceil() operation on +// a dense array \a ceil() expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) ceil( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Applies the \a trunc() function to a dense array \a trunc() expressions. +// \ingroup dense_array +// +// \param dm The dense array \a trunc() expression. +// \return The resulting dense array. +// +// This function implements a performance optimized treatment of the \a trunc() operation on +// a dense array \a trunc() expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) trunc( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Applies the \a round() function to a dense array \a round() expressions. +// \ingroup dense_array +// +// \param dm The dense array \a round() expression. +// \return The resulting dense array. +// +// This function implements a performance optimized treatment of the \a round() operation on +// a dense array \a round() expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) round( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Complex conjugate function for complex conjugate dense array expressions. +// \ingroup dense_array +// +// \param dm The complex conjugate dense array expression. +// \return The original dense array. +// +// This function implements a performance optimized treatment of the complex conjugate operation +// on a dense array complex conjugate expression. It returns an expression representing the +// original dense array: + + \code + blaze::DynamicArray< complex > A, B; + // ... Resizing and initialization + B = conj( conj( A ) ); + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) conj( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm.operand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Complex conjugate function for conjugate transpose dense array expressions. +// \ingroup dense_array +// +// \param dm The conjugate transpose dense array expression. +// \return The transpose dense array. +// +// This function implements a performance optimized treatment of the complex conjugate operation +// on a dense array conjugate transpose expression. It returns an expression representing the +// transpose of the dense array: + + \code + blaze::DynamicArray< complex > A, B; + // ... Resizing and initialization + B = conj( ctrans( A ) ); + \endcode +*/ +template< typename MT // Type of the dense array + , typename Conj // Type of the custom operation + , size_t ... CTAs> // Compile time arguments +inline decltype(auto) conj( const DTensTransExpr, CTAs... >& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DTensTransExpr; + return ReturnType( dm.operand().operand(), (~dm).idces() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Real part function for real part dense array expressions. +// \ingroup dense_array +// +// \param dm The real part dense array expression. +// \return The real part of each single element of \a dm. +// +// This function implements a performance optimized treatment of the real part operation on +// a dense array real part expression. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) real( const DArrMapExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsAligned< DArrMapExpr > + : public IsAligned +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsPadded< DArrMapExpr > + : public IsPadded +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsSymmetric< DArrMapExpr > + : public YieldsSymmetric +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsHermitian< DArrMapExpr > + : public YieldsHermitian +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsLower< DArrMapExpr > + : public YieldsLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsUniLower< DArrMapExpr > + : public YieldsUniLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsStrictlyLower< DArrMapExpr > + : public YieldsStrictlyLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsUpper< DArrMapExpr > + : public YieldsUpper +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsUniUpper< DArrMapExpr > + : public YieldsUniUpper +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP > +struct IsStrictlyUpper< DArrMapExpr > + : public YieldsStrictlyUpper +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrNormExpr.h b/blaze_tensor/math/expressions/DArrNormExpr.h new file mode 100644 index 0000000..ae450b4 --- /dev/null +++ b/blaze_tensor/math/expressions/DArrNormExpr.h @@ -0,0 +1,435 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/DArrNormExpr.h +// \brief Header file for the dense array norm expression +// +// Copyright (C) 2012-2019 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRNORMEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRNORMEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the dense array norms. +// \ingroup dense_array +*/ +template< typename MT // Type of the dense array + , typename Abs // Type of the abs operation + , typename Power > // Type of the power operation +struct DArrNormHelper +{ + //**Type definitions**************************************************************************** + //! Element type of the dense array expression. + using ET = ElementType_t; + + //! Composite type of the dense array expression. + using CT = RemoveReference_t< CompositeType_t >; + //********************************************************************************************** + + //********************************************************************************************** + static constexpr bool value = + ( useOptimizedKernels && + CT::simdEnabled && + If_t< HasSIMDEnabled_v && HasSIMDEnabled_v + , And< GetSIMDEnabled, GetSIMDEnabled > + , And< HasLoad, HasLoad > >::value && + HasSIMDAdd_v< ElementType_t, ElementType_t > ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Computes a custom norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \param abs The functor for the abs operation. +// \param power The functor for the power operation. +// \param root The functor for the root operation. +// \return The norm of the given dense array. +// +// This function computes a custom norm of the given dense array by means of the given functors. +// The following example demonstrates the computation of the L2 norm by means of the blaze::Pow2 +// and blaze::Sqrt functors: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l2 = norm( A, blaze::Pow2(), blaze::Sqrt() ); + \endcode +*/ +template< typename MT // Type of the dense array + , typename Abs // Type of the abs operation + , typename Power // Type of the power operation + , typename Root > // Type of the root operation +decltype(auto) norm_backend( const DenseArray& dm, Abs abs, Power power, Root root ) +{ + using CT = CompositeType_t; + using ET = ElementType_t; + using RT = decltype( evaluate( root( std::declval() ) ) ); + + if( ArrayDimAnyOf( ( ~dm ).dimensions(), []( size_t i ) { return i == 0; } ) ) return RT{}; + + CT tmp( ~dm ); + + BLAZE_INTERNAL_ASSERT( tmp.dimensions() == (~dm).dimensions(), "Invalid number of elements" ); + + using AT = RemoveCV_t >; + constexpr size_t N = AT::num_dimensions(); + + std::array< size_t, N > dims{}; + ET norm( power( abs( tmp( dims ) ) ) ); + + ArrayForEachGrouped( ( ~dm ).dimensions(), + [&]( std::array< size_t, N > const& dims ) { + norm += power( abs( tmp( dims ) ) ); + } ); + + return evaluate( root( norm ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the L2 norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The L2 norm of the given dense array. +// +// This function computes the L2 norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l2 = norm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) norm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return norm_backend( ~dm, SqrAbs(), Noop(), Sqrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the squared L2 norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The squared L2 norm of the given dense array. +// +// This function computes the squared L2 norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l2 = sqrNorm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) sqrNorm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return norm_backend( ~dm, SqrAbs(), Noop(), Noop() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the L1 norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The L1 norm of the given dense array. +// +// This function computes the L1 norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l1 = l1Norm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) l1Norm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return norm_backend( ~dm, Abs(), Noop(), Noop() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the L2 norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The L2 norm of the given dense array. +// +// This function computes the L2 norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l2 = l2Norm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) l2Norm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return norm_backend( ~dm, SqrAbs(), Noop(), Sqrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the L3 norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The L3 norm of the given dense array. +// +// This function computes the L3 norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l3 = l3Norm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) l3Norm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return norm_backend( ~dm, Abs(), Pow3(), Cbrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the L4 norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The L4 norm of the given dense array. +// +// This function computes the L4 norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double l4 = l4Norm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) l4Norm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return norm_backend( ~dm, SqrAbs(), Pow2(), Qdrt() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the Lp norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \param p The norm parameter (p > 0). +// \return The Lp norm of the given dense array. +// +// This function computes the Lp norm of the given dense array, where the norm is specified by +// the runtime argument \a p: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double lp = lpNorm( A, 2.3 ); + \endcode + +// \note The norm parameter \a p is expected to be larger than 0. This precondition is only checked +// by a user assertion. +*/ +template< typename MT // Type of the dense array + , typename ST > // Type of the norm parameter +decltype(auto) lpNorm( const DenseArray& dm, ST p ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( !isZero( p ), "Invalid p for Lp norm detected" ); + + using ScalarType = MultTrait_t< UnderlyingBuiltin_t, decltype( inv( p ) ) >; + return norm_backend( ~dm, Abs(), UnaryPow( p ), UnaryPow( inv( p ) ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the Lp norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The Lp norm of the given dense array. +// +// This function computes the Lp norm of the given dense array, where the norm is specified by +// the runtime argument \a P: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double lp = lpNorm<2>( A ); + \endcode + +// \note The norm parameter \a P is expected to be larger than 0. A value of 0 results in a +// compile time error!. +*/ +template< size_t P // Compile time norm parameter + , typename MT > // Type of the dense array +inline decltype(auto) lpNorm( const DenseArray& dm ) +{ + BLAZE_STATIC_ASSERT_MSG( P > 0UL, "Invalid norm parameter detected" ); + + using Norms = TypeList< L1Norm, L2Norm, L3Norm, L4Norm, LpNorm

>; + using Norm = typename TypeAt< Norms, min( P-1UL, 4UL ) >::Type; + + return Norm()( ~dm ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Computes the maximum norm for the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the norm computation. +// \return The maximum norm of the given dense array. +// +// This function computes the maximum norm of the given dense array: + + \code + blaze::DenseArray A; + // ... Resizing and initialization + const double max = maxNorm( A ); + \endcode +*/ +template< typename MT > // Type of the dense array +decltype(auto) maxNorm( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return max( abs( ~dm ) ); +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrReduceExpr.h b/blaze_tensor/math/expressions/DArrReduceExpr.h new file mode 100644 index 0000000..331ebe7 --- /dev/null +++ b/blaze_tensor/math/expressions/DArrReduceExpr.h @@ -0,0 +1,1371 @@ +//================================================================================================= +/*! +// \file blaze/math/expressions/DArrReduceExpr.h +// \brief Header file for the dense array reduce expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRREDUCEEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRREDUCEEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base template for dense array reduction operations. +// \ingroup dense_array_expression +// +// The ReducedArray class represents the compile time expression for partial reduction operations +// of dense matrices. +*/ +template< typename MT // Type of the dense array + , typename OP // Type of the reduction operation + , size_t RF > // Reduction flag +class ReducedArray; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR ARBITRARY REDUCTION OPERATIONS OF ARRAYS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Expression object for arbitrary dense array reduction operations. +// \ingroup dense_array_expression +// +// This specialization of the ReducedArray class template represents the compile time expression +// for row-wise reduction operations of dense matrices. +*/ +template< typename MT // Type of the dense array + , typename OP // Type of the reduction operation + , size_t R > // DImension along which to perform reduction +class ReducedArray + : public ArrReduceExpr< DenseArray< ReducedArray >, R > + , private Computation +{ + private: + //**Type definitions**************************************************************************** + using RT = ResultType_t; //!< Result type of the dense array expression. + using ET = ElementType_t; //!< Element type of the dense array expression. + //********************************************************************************************** + + //**Serial evaluation strategy****************************************************************** + //! Compilation switch for the serial evaluation strategy of the reduction expression. + /*! The \a useAssign compile time constant expression represents a compilation switch for + the serial evaluation strategy of the reduction expression. In case the dense array + operand requires an intermediate evaluation, \a useAssign will be set to 1 and the + reduction expression will be evaluated via the \a assign function family. Otherwise + \a useAssign will be set to 0 and the expression will be evaluated via the subscript + operator. */ + static constexpr bool useAssign = RequiresEvaluation_v; + + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename VT > + static constexpr bool UseAssign_v = useAssign; + /*! \endcond */ + //********************************************************************************************** + + //**Parallel evaluation strategy**************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + /*! This variable template is a helper for the selection of the parallel evaluation strategy. + In case the dense array operand is not SMP assignable and requires an intermediate + evaluation, the variable is set to 1 and the expression specific evaluation strategy + is selected. Otherwise the variable is set to 0 and the default strategy is chosen. */ + template< typename VT > + static constexpr bool UseSMPAssign_v = ( !MT::smpAssignable && useAssign ); + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + using This = ReducedArray; //!< Type of this ReducedArray instance. + using ResultType = ReduceTrait_t; //!< Result type for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Resulting element type. + using SIMDType = SIMDTrait_t; //!< Resulting SIMD element type. + using ReturnType = const ElementType; //!< Return type for expression template evaluations. + + //! Data type for composite expression templates. + using CompositeType = If_t< useAssign, const ResultType, const ReducedArray& >; + + //! Composite type of the left-hand side dense array expression. + using Operand = If_t< IsExpression_v, const MT, const MT& >; + + //! Data type of the custom unary operation. + using Operation = OP; + //********************************************************************************************** + + //**ConstIterator class definition************************************************************** + /*!\brief Iterator over the elements of the dense array. + */ + class ConstIterator + { + public: + //**Type definitions************************************************************************* + using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. + using ValueType = ElementType; //!< Type of the underlying elements. + using PointerType = ElementType*; //!< Pointer return type. + using ReferenceType = ElementType&; //!< Reference return type. + using DifferenceType = ptrdiff_t; //!< Difference between two iterators. + + // STL iterator requirements + using iterator_category = IteratorCategory; //!< The iterator category. + using value_type = ValueType; //!< Type of the underlying elements. + using pointer = PointerType; //!< Pointer return type. + using reference = ReferenceType; //!< Reference return type. + using difference_type = DifferenceType; //!< Difference between two iterators. + //******************************************************************************************* + + //**Constructor****************************************************************************** + /*!\brief Constructor for the ConstIterator class. + // + // \param dm The dense array operand of the reduction expression. + // \param i Index to the initial array page. + // \param i Index to the array row. + // \param op The reduction operation. + */ + explicit inline ConstIterator( Operand dm, size_t k, OP op ) + : dm_ ( dm ) // Dense array of the reduction expression + , k_ ( k ) // Index to the current array page + , op_ ( op ) // The reduction operation + {} + //******************************************************************************************* + + //**Addition assignment operator************************************************************* + /*!\brief Addition assignment operator. + // + // \param inc The increment of the iterator. + // \return The incremented iterator. + */ + inline ConstIterator& operator+=( size_t inc ) { + k_ += inc; + return *this; + } + //******************************************************************************************* + + //**Subtraction assignment operator********************************************************** + /*!\brief Subtraction assignment operator. + // + // \param dec The decrement of the iterator. + // \return The decremented iterator. + */ + inline ConstIterator& operator-=( size_t dec ) { + k_ -= dec; + return *this; + } + //******************************************************************************************* + + //**Prefix increment operator**************************************************************** + /*!\brief Pre-increment operator. + // + // \return Reference to the incremented iterator. + */ + inline ConstIterator& operator++() { + ++k_; + return *this; + } + //******************************************************************************************* + + //**Postfix increment operator*************************************************************** + /*!\brief Post-increment operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator++( int ) { + return ConstIterator( k_++ ); + } + //******************************************************************************************* + + //**Prefix decrement operator**************************************************************** + /*!\brief Pre-decrement operator. + // + // \return Reference to the decremented iterator. + */ + inline ConstIterator& operator--() { + --k_; + return *this; + } + //******************************************************************************************* + + //**Postfix decrement operator*************************************************************** + /*!\brief Post-decrement operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator--( int ) { + return ConstIterator( k_-- ); + } + //******************************************************************************************* + + //**Element access operator****************************************************************** + /*!\brief Direct access to the element at the current iterator position. + // + // \return The resulting value. + */ + inline ReturnType operator*() const { + return reduce( arrayslice< R >( dm_, k_, unchecked ), op_ ); + } + //******************************************************************************************* + + //**Equality operator************************************************************************ + /*!\brief Equality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators refer to the same element, \a false if not. + */ + inline bool operator==( const ConstIterator& rhs ) const { + return k_ == rhs.k_; + } + //******************************************************************************************* + + //**Inequality operator********************************************************************** + /*!\brief Inequality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators don't refer to the same element, \a false if they do. + */ + inline bool operator!=( const ConstIterator& rhs ) const { + return k_ != rhs.k_; + } + //******************************************************************************************* + + //**Less-than operator*********************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller, \a false if not. + */ + inline bool operator<( const ConstIterator& rhs ) const { + return k_ < rhs.k_; + } + //******************************************************************************************* + + //**Greater-than operator******************************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater, \a false if not. + */ + inline bool operator>( const ConstIterator& rhs ) const { + return !(*this <= rhs); + } + //******************************************************************************************* + + //**Less-or-equal-than operator************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. + */ + inline bool operator<=( const ConstIterator& rhs ) const { + return k_ <= rhs.k_; + } + //******************************************************************************************* + + //**Greater-or-equal-than operator*********************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater or equal, \a false if not. + */ + inline bool operator>=( const ConstIterator& rhs ) const { + return !(*this < rhs); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Calculating the number of elements between two iterators. + // + // \param rhs The right-hand side iterator. + // \return The number of elements between the two iterators. + */ + inline DifferenceType operator-( const ConstIterator& rhs ) const { + return k_ - rhs.k_; + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between a ConstIterator and an integral value. + // + // \param it The iterator to be incremented. + // \param inc The number of elements the iterator is incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { + return ConstIterator( it.k_ + inc ); + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between an integral value and a ConstIterator. + // + // \param inc The number of elements the iterator is incremented. + // \param it The iterator to be incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { + return ConstIterator( it.k_ + inc ); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Subtraction between a ConstIterator and an integral value. + // + // \param it The iterator to be decremented. + // \param dec The number of elements the iterator is decremented. + // \return The decremented iterator. + */ + friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { + return ConstIterator( it.k_ - dec ); + } + //******************************************************************************************* + + private: + //**Member variables************************************************************************* + Operand dm_; //!< Dense array of the reduction expression. + size_t k_; //!< Index to the current array page. + OP op_; //!< The reduction operation. + //******************************************************************************************* + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = false; + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = MT::smpAssignable; + //********************************************************************************************** + + //**Constructor********************************************************************************* + /*!\brief Constructor for the ReducedArray class. + // + // \param dm The array operand of the reduction expression. + // \param op The reduction operation. + */ + explicit inline ReducedArray( const MT& dm, OP op ) noexcept + : dm_( dm ) // Dense array of the reduction expression + , op_( op ) // The reduction operation + {} + //********************************************************************************************** + + //**Subscript operator************************************************************************** + /*!\brief Subscript operator for the direct access to the array elements. + // + // \param index Access index. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + */ + template< typename... Dims > + inline ReturnType operator()( Dims... dims ) const { + return reduce( arrayslice( dm_, dims..., unchecked ), op_ ); + } + //********************************************************************************************** + + //**At function********************************************************************************* + /*!\brief Checked access to the array elements. + // + // \param index Access index. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + // \exception std::out_of_range Invalid array access index. + */ + template< typename... Dims > + inline ReturnType at( Dims... dims ) const { + constexpr size_t indices[] = {dims...}; + + ArrayDimForEach( dims_, [&]( size_t i ) { + if( indices[i] >= dims_[i + 1] ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + return (*this)(dims...); + } + //********************************************************************************************** + + //**Begin function****************************************************************************** + /*!\brief Returns an iterator to the first element of the dense array. + // + // \return Iterator to the first element of the dense array. + */ + inline ConstIterator begin( size_t i ) const { + return ConstIterator( dm_, i, op_ ); + } + //********************************************************************************************** + + //**End function******************************************************************************** + /*!\brief Returns an iterator just past the last non-zero element of the dense array. + // + // \return Iterator just past the last non-zero element of the dense array. + */ + inline ConstIterator end( size_t i ) const { + return ConstIterator( dm_, i, op_ ); + } + //********************************************************************************************** + + //**Num_dimensions function******************************************************************************* + /*!\brief Returns the current number of dimensions of the array. + // + // \return The size of the array. + */ + inline static constexpr size_t num_dimensions() noexcept { + return RemoveCV_t>::num_dimensions(); + } + //********************************************************************************************** + + //**Dimensions function**************************************************************************** + /*!\brief Returns the current dimensions of the array. + // + // \return The dimensions of the array. + */ + inline decltype(auto) dimensions() const noexcept { + return dm_.dimensions(); + } + //********************************************************************************************** + + //**Pages function******************************************************************************* + /*!\brief Returns the current size/dimension of the array. + // + // \return The size of the array. + */ + template< size_t Dim > + inline size_t dimension() const noexcept { + return dm_.template dimension(); + } + //********************************************************************************************** + + //**Operand access****************************************************************************** + /*!\brief Returns the dense array operand. + // + // \return The dense array operand. + */ + inline Operand operand() const noexcept { + return dm_; + } + //********************************************************************************************** + + //**Operation access**************************************************************************** + /*!\brief Returns a copy of the reduction operation. + // + // \return A copy of the reduction operation. + */ + inline Operation operation() const { + return op_; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can alias with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case an aliasing effect is possible, \a false if not. + */ + template< typename T > + inline bool canAlias( const T* alias ) const noexcept { + return ( dm_.isAliased( alias ) ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression is aliased with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case the given alias is contained in this expression, \a false if not. + */ + template< typename T > + inline bool isAliased( const T* alias ) const noexcept { + return ( dm_.isAliased( alias ) ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the operands of the expression are properly aligned in memory. + // + // \return \a true in case the operands are aligned, \a false if not. + */ + inline bool isAligned() const noexcept { + return false; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can be used in SMP assignments. + // + // \return \a true in case the expression can be used in SMP assignments, \a false if not. + */ + inline bool canSMPAssign() const noexcept { + return dm_.canSMPAssign() || ( rows() * columns() > SMP_DMATREDUCE_THRESHOLD ); + } + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + Operand dm_; //!< Dense array of the reduction expression. + Operation op_; //!< The reduction operation. + //********************************************************************************************** + + //**Assignment to tensors*********************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a row-wise row-major + // dense array reduction expression to a array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression specific + // parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto assign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + assign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to tensors************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Addition assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be added. + // \return void + // + // This function implements the performance optimized addition assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto addAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + addAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Subtraction assignment to tensors*********************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Subtraction assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be subtracted. + // \return void + // + // This function implements the performance optimized subtraction assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto subAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + subAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Multiplication assignment to tensors******************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Multiplication assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be multiplied. + // \return void + // + // This function implements the performance optimized multiplication assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto multAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + multAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Division assignment to tensors************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Division assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression divisor. + // \return void + // + // This function implements the performance optimized division assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto divAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + divAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to tensors******************************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a row-wise row-major + // dense array reduction expression to a array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression specific + // parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP addition assignment to tensors********************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP addition assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be added. + // \return void + // + // This function implements the performance optimized SMP addition assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpAddAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpAddAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP subtraction assignment to tensors******************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP subtraction assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be subtracted. + // \return void + // + // This function implements the performance optimized SMP subtraction assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpSubAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpSubAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP multiplication assignment to tensors**************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP multiplication assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be multiplied. + // \return void + // + // This function implements the performance optimized SMP multiplication assignment of a + // row-wise dense array reduction expression to a array. Due to the explicit + // application of the SFINAE principle, this function can only be selected by the compiler + // in case the expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpMultAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpMultAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP division assignment to tensors********************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP division assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression divisor. + // \return void + // + // This function implements the performance optimized SMP division assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpDivAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpDivAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); + /*! \endcond */ + //********************************************************************************************** +}; +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the dense array reduction operation. +// \ingroup dense_array +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +struct ArrayHelper +{ + //**Type definitions**************************************************************************** + //! Composite type of the dense array expression. + using CT = RemoveReference_t< CompositeType_t >; + + //! Element type of the dense array expression. + using ET = ElementType_t; + + //! Definition of the HasSIMDEnabled type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled ); + + //! Definition of the HasLoad type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load ); + //********************************************************************************************** + + //********************************************************************************************** + static constexpr bool value = + ( CT::simdEnabled && + If_t< HasSIMDEnabled_v, GetSIMDEnabled, HasLoad >::value ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default backend implementation of the reduction of a dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +// +// This function implements the performance optimized reduction operation for a dense +// array. Due to the explicit application of the SFINAE principle, this function can only be +// selected by the compiler in case vectorization cannot be applied. +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline ElementType_t darrayreduce( const DenseArray& dm, OP op ) +{ + using CT = CompositeType_t; + using ET = ElementType_t; + + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); + + std::array< size_t, N > dims{}; + + if( ArrayDimAnyOf( ( ~dm ).dimensions(), []( size_t i ) { return i == 0; } ) ) return ET{}; + if( ArrayDimAllOf( ( ~dm ).dimensions(), []( size_t i ) { return i == 1; } ) ) return ( ~dm )( dims ); + + CT tmp( ~dm ); + + BLAZE_INTERNAL_ASSERT( tmp.dimensions() == (~dm).dimensions(), "Invalid number of elements" ); + + ET redux{}; + + ArrayForEachGrouped( ( ~dm ).dimensions(), + [&]( std::array< size_t, N > const& dims ) { + redux = op( redux, tmp( dims ) ); + } ); + + return redux; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Performs a custom reduction operation on the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the given dense array \a dm by means of the given reduction operation +// \a op: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + + const double totalsum1 = reduce( A, blaze::Add() ); + const double totalsum2 = reduce( A, []( double a, double b ){ return a + b; } ); + \endcode + +// As demonstrated in the example it is possible to pass any binary callable as custom reduction +// operation. However, for instance in the case of lambdas the vectorization of the reduction +// operation is compiler dependent and might not perform at peak performance. However, it is also +// possible to create vectorized custom operations. See \ref custom_operations for a detailed +// overview of the possibilities of custom operations. +// +// Please note that the evaluation order of the reduction operation is unspecified. Thus the +// behavior is non-deterministic if \a op is not associative or not commutative. Also, the +// operation is undefined if the given reduction operation modifies the values. +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline decltype(auto) reduce( const DenseArray& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return darrayreduce( ~dm, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation for custom reduction operations on dense matrices. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +*/ +template< size_t RF // Reduction flag + , typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline const ReducedArray reduce_backend( const DenseArray& dm, OP op ) +{ + return ReducedArray( ~dm, op ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Performs a custom reduction operation on the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the rows or columns of the given dense array \a dm by means of the +// given reduction operation \a op. In case the reduction flag \a RF is set to \a blaze::columnwise, +// the elements of the array are reduced column-wise and the result is a row array. In case +// \a RF is set to \a blaze::rowwise, the elements of the array are reduced row-wise and the +// result is a column array: + + \code + using blaze::columnwise; + + blaze::DynamicArray A; + blaze::DynamicMatrix colsum1, colsum2; + // ... Resizing and initialization + + colsum1 = reduce( A, blaze::Add() ); + colsum2 = reduce( A, []( double a, double b ){ return a + b; } ); + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A; + blaze::DynamicMatrix rowsum1, rowsum2; + // ... Resizing and initialization + + rowsum1 = reduce( A, blaze::Add() ); + rowsum2 = reduce( A, []( double a, double b ){ return a + b; } ); + \endcode + +// As demonstrated in the examples it is possible to pass any binary callable as custom reduction +// operation. However, for instance in the case of lambdas the vectorization of the reduction +// operation is compiler dependent and might not perform at peak performance. However, it is also +// possible to create vectorized custom operations. See \ref custom_operations for a detailed +// overview of the possibilities of custom operations. +// +// Please note that the evaluation order of the reduction operation is unspecified. Thus the +// behavior is non-deterministic if \a op is not associative or not commutative. Also, the +// operation is undefined if the given reduction operation modifies the values. +*/ +template< size_t RF // Reduction flag + , typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline decltype(auto) reduce( const DenseArray& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce_backend( ~dm, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of addition. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the given dense array \a dm by means of addition: + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalsum = sum( A ); // Results in 10 + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sum( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Add() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of addition. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the rows or columns of the given dense array \a dm by means of +// addition. In case the reduction flag \a RF is set to \a blaze::columnwise, the elements of +// the array are reduced column-wise and the result is a row array. In case \a RF is set to +// \a blaze::rowwise, the elements of the array are reduced row-wise and the result is a +// column array: + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colsum; + + colsum = sum( A ); // Results in ( 2, 3, 6 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowsum; + + rowsum = sum( A ); // Results in ( 3, 8 ) + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) sum( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Add() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of multiplication. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the given dense array \a dm by means of multiplication: + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalprod = prod( A ); // Results in 24 + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) prod( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Mult() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of multiplication. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the rows or columns of the given dense array \a dm by means of +// multiplication. In case the reduction flag \a RF is set to \a blaze::columnwise, the elements +// of the array are reduced column-wise and the result is a row array. In case \a RF is set to +// \a blaze::rowwise, the elements of the array are reduced row-wise and the result is a column +// array: + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colprod; + + colprod = prod( A ); // Results in ( 1, 0, 8 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowprod; + + rowprod = prod( A ); // Results in ( 0, 12 ) + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) prod( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Mult() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the smallest element of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The smallest dense array element. +// +// This function returns the smallest element of the given dense array. This function can only +// be used for element types that support the smaller-than relationship. In case the given array +// currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in +// case of fundamental data types). + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalmin = min( A ); // Results in 1 + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) min( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Min() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the smallest element of each row/columns of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The smallest elements in each row/column. +// +// This function returns the smallest element of each row/column of the given dense array \a dm. +// In case the reduction flag \a RF is set to \a blaze::columnwise, a row array containing the +// smallest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a +// column array containing the smallest element of each row is returned. + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colmin; + + colmin = min( A ); // Results in ( 1, 0, 2 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowmin; + + rowmin = min( A ); // Results in ( 0, 1 ) + \endcode +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) min( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Min() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the largest element of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The largest dense array element. +// +// This function returns the largest element of the given dense array. This function can only +// be used for element types that support the smaller-than relationship. In case the given martix +// currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in +// case of fundamental data types). + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalmax = max( A ); // Results in 4 + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) max( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Max() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the largest element of each row/columns of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The largest elements in each row/column. +// +// This function returns the largest element of each row/column of the given dense array \a dm. +// In case the reduction flag \a RF is set to \a blaze::columnwise, a row array containing the +// largest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a +// column array containing the largest element of each row is returned. + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colmax; + + colmax = max( A ); // Results in ( 1, 3, 4 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowmax; + + rowmax = max( A ); // Results in ( 2, 4 ) + \endcode +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) max( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Max() ); +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrScalarDivExpr.h b/blaze_tensor/math/expressions/DArrScalarDivExpr.h new file mode 100644 index 0000000..ce368ea --- /dev/null +++ b/blaze_tensor/math/expressions/DArrScalarDivExpr.h @@ -0,0 +1,1170 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/DArrScalarDivExpr.h +// \brief Header file for the dense array/scalar division expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_ARRAY_MATH_EXPRESSIONS_DARRSCALARDIVEXPR_H_ +#define _BLAZE_ARRAY_MATH_EXPRESSIONS_DARRSCALARDIVEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DARRSCALARDIVEXPR +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Expression object for divisions of a dense array by a scalar. +// \ingroup dense_array_expression +// +// The DArrScalarDivExpr class represents the compile time expression for divisions of dense +// matrices and by scalar values. +*/ +template< typename MT // Type of the left-hand side dense array + , typename ST > // Type of the right-hand side scalar value +class DArrScalarDivExpr + : public ArrScalarDivExpr< DenseArray< DArrScalarDivExpr > > + , private Computation +{ + private: + //**Type definitions**************************************************************************** + using RT = ResultType_t; //!< Result type of the dense array expression. + using RN = ReturnType_t; //!< Return type of the dense array expression. + using ET = ElementType_t; //!< Element type of the dense array expression. + using CT = CompositeType_t; //!< Composite type of the dense array expression. + //********************************************************************************************** + + //**Return type evaluation********************************************************************** + //! Compilation switch for the selection of the subscript operator return type. + /*! The \a returnExpr compile time constant expression is a compilation switch for the + selection of the \a ReturnType. If the array operand returns a temporary vector + or array, \a returnExpr will be set to \a false and the subscript operator will + return it's result by value. Otherwise \a returnExpr will be set to \a true and + the subscript operator may return it's result as an expression. */ + static constexpr bool returnExpr = !IsTemporary_v; + + //! Expression return type for the subscript operator. + using ExprReturnType = decltype( std::declval() / std::declval() ); + //********************************************************************************************** + + //**Serial evaluation strategy****************************************************************** + //! Compilation switch for the serial evaluation strategy of the division expression. + /*! The \a useAssign compile time constant expression represents a compilation switch for + the serial evaluation strategy of the division expression. In case the given dense + array expression of type \a MT is a computation expression and requires an intermediate + evaluation, \a useAssign will be set to 1 and the division expression will be evaluated + via the \a assign function family. Otherwise \a useAssign will be set to 0 and the + expression will be evaluated via the subscript operator. */ + static constexpr bool useAssign = IsComputation_v && RequiresEvaluation_v; + + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool UseAssign_v = useAssign; + /*! \endcond */ + //********************************************************************************************** + + //**Parallel evaluation strategy**************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + /*! This variable template is a helper for the selection of the parallel evaluation strategy. + In case either the target array or the dense array operand is not SMP assignable and the + array operand is a computation expression that requires an intermediate evaluation, the + variable is set to 1 and the expression specific evaluation strategy is selected. Otherwise + the variable is set to 0 and the default strategy is chosen. */ + template< typename MT2 > + static constexpr bool UseSMPAssign_v = + ( ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign ); + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + using This = DArrScalarDivExpr; //!< Type of this DArrScalarDivExpr instance. + using ResultType = DivTrait_t; //!< Result type for expression template evaluations. + using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Resulting element type. + + //! Return type for expression template evaluations. + using ReturnType = const If_t< returnExpr, ExprReturnType, ElementType >; + + //! Data type for composite expression templates. + using CompositeType = If_t< useAssign, const ResultType, const DArrScalarDivExpr& >; + + //! Composite type of the left-hand side dense array expression. + using LeftOperand = If_t< IsExpression_v, const MT, const MT& >; + + //! Composite type of the right-hand side scalar value. + using RightOperand = ST; + //********************************************************************************************** + + //**ConstIterator class definition************************************************************** + /*!\brief Iterator over the elements of the dense array. + */ + class ConstIterator + { + public: + //**Type definitions************************************************************************* + using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. + using ValueType = ElementType; //!< Type of the underlying elements. + using PointerType = ElementType*; //!< Pointer return type. + using ReferenceType = ElementType&; //!< Reference return type. + using DifferenceType = ptrdiff_t; //!< Difference between two iterators. + + // STL iterator requirements + using iterator_category = IteratorCategory; //!< The iterator category. + using value_type = ValueType; //!< Type of the underlying elements. + using pointer = PointerType; //!< Pointer return type. + using reference = ReferenceType; //!< Reference return type. + using difference_type = DifferenceType; //!< Difference between two iterators. + + //! ConstIterator type of the dense array expression. + using IteratorType = ConstIterator_t; + //******************************************************************************************* + + //**Constructor****************************************************************************** + /*!\brief Constructor for the ConstIterator class. + // + // \param iterator Iterator to the initial element. + // \param scalar Scalar of the multiplication expression. + */ + explicit inline ConstIterator( IteratorType iterator, RightOperand scalar ) + : iterator_( iterator ) // Iterator to the current element + , scalar_ ( scalar ) // Scalar of the multiplication expression + {} + //******************************************************************************************* + + //**Addition assignment operator************************************************************* + /*!\brief Addition assignment operator. + // + // \param inc The increment of the iterator. + // \return The incremented iterator. + */ + inline ConstIterator& operator+=( size_t inc ) { + iterator_ += inc; + return *this; + } + //******************************************************************************************* + + //**Subtraction assignment operator********************************************************** + /*!\brief Subtraction assignment operator. + // + // \param dec The decrement of the iterator. + // \return The decremented iterator. + */ + inline ConstIterator& operator-=( size_t dec ) { + iterator_ -= dec; + return *this; + } + //******************************************************************************************* + + //**Prefix increment operator**************************************************************** + /*!\brief Pre-increment operator. + // + // \return Reference to the incremented iterator. + */ + inline ConstIterator& operator++() { + ++iterator_; + return *this; + } + //******************************************************************************************* + + //**Postfix increment operator*************************************************************** + /*!\brief Post-increment operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator++( int ) { + return ConstIterator( iterator_++ ); + } + //******************************************************************************************* + + //**Prefix decrement operator**************************************************************** + /*!\brief Pre-decrement operator. + // + // \return Reference to the decremented iterator. + */ + inline ConstIterator& operator--() { + --iterator_; + return *this; + } + //******************************************************************************************* + + //**Postfix decrement operator*************************************************************** + /*!\brief Post-decrement operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator--( int ) { + return ConstIterator( iterator_-- ); + } + //******************************************************************************************* + + //**Element access operator****************************************************************** + /*!\brief Direct access to the element at the current iterator position. + // + // \return The resulting value. + */ + inline ReturnType operator*() const { + return *iterator_ / scalar_; + } + //******************************************************************************************* + + //**Load function**************************************************************************** + /*!\brief Access to the SIMD elements of the array. + // + // \return The resulting SIMD element. + */ + inline auto load() const noexcept { + return iterator_.load() / set( scalar_ ); + } + //******************************************************************************************* + + //**Equality operator************************************************************************ + /*!\brief Equality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators refer to the same element, \a false if not. + */ + inline bool operator==( const ConstIterator& rhs ) const { + return iterator_ == rhs.iterator_; + } + //******************************************************************************************* + + //**Inequality operator********************************************************************** + /*!\brief Inequality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators don't refer to the same element, \a false if they do. + */ + inline bool operator!=( const ConstIterator& rhs ) const { + return iterator_ != rhs.iterator_; + } + //******************************************************************************************* + + //**Less-than operator*********************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller, \a false if not. + */ + inline bool operator<( const ConstIterator& rhs ) const { + return iterator_ < rhs.iterator_; + } + //******************************************************************************************* + + //**Greater-than operator******************************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater, \a false if not. + */ + inline bool operator>( const ConstIterator& rhs ) const { + return iterator_ > rhs.iterator_; + } + //******************************************************************************************* + + //**Less-or-equal-than operator************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. + */ + inline bool operator<=( const ConstIterator& rhs ) const { + return iterator_ <= rhs.iterator_; + } + //******************************************************************************************* + + //**Greater-or-equal-than operator*********************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater or equal, \a false if not. + */ + inline bool operator>=( const ConstIterator& rhs ) const { + return iterator_ >= rhs.iterator_; + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Calculating the number of elements between two iterators. + // + // \param rhs The right-hand side iterator. + // \return The number of elements between the two iterators. + */ + inline DifferenceType operator-( const ConstIterator& rhs ) const { + return iterator_ - rhs.iterator_; + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between a ConstIterator and an integral value. + // + // \param it The iterator to be incremented. + // \param inc The number of elements the iterator is incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { + return ConstIterator( it.iterator_ + inc, it.scalar_ ); + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between an integral value and a ConstIterator. + // + // \param inc The number of elements the iterator is incremented. + // \param it The iterator to be incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { + return ConstIterator( it.iterator_ + inc, it.scalar_ ); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Subtraction between a ConstIterator and an integral value. + // + // \param it The iterator to be decremented. + // \param dec The number of elements the iterator is decremented. + // \return The decremented iterator. + */ + friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { + return ConstIterator( it.iterator_ - dec, it.scalar_ ); + } + //******************************************************************************************* + + private: + //**Member variables************************************************************************* + IteratorType iterator_; //!< Iterator to the current element. + RightOperand scalar_; //!< Scalar of the multiplication expression. + //******************************************************************************************* + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = + ( MT::simdEnabled && IsNumeric_v && + ( HasSIMDDiv_v || HasSIMDDiv_v,ST> ) ); + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = MT::smpAssignable; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + //**Constructor********************************************************************************* + /*!\brief Constructor for the DArrScalarDivExpr class. + // + // \param array The left-hand side dense array of the division expression. + // \param scalar The right-hand side scalar of the division expression. + */ + explicit inline DArrScalarDivExpr( const MT& array, ST scalar ) noexcept + : array_( array ) // Left-hand side dense array of the division expression + , scalar_( scalar ) // Right-hand side scalar of the division expression + {} + //********************************************************************************************** + + //**Access operator***************************************************************************** + /*!\brief 2D-access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + */ + template< typename... Dims > + inline ReturnType operator()( Dims... dims ) const { + return array_( dims... ) / scalar_; + } + //********************************************************************************************** + + //**At function********************************************************************************* + /*!\brief Checked access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + // \exception std::out_of_range Invalid array access index. + */ + template< typename... Dims > + inline ReturnType at( Dims... dims ) const { + return ( *this )( dims... ); + } + //********************************************************************************************** + + //**Load function******************************************************************************* + /*!\brief Access to the SIMD elements of the array. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return Reference to the accessed values. + */ + template< typename... Dims > + BLAZE_ALWAYS_INLINE auto load( Dims... dims ) const noexcept { + return array_.load( dims... ) / set( scalar_ ); + } + //********************************************************************************************** + + //**Begin function****************************************************************************** + /*!\brief Returns an iterator to the first non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator to the first non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator begin( size_t i, Dims... dims ) const { + return ConstIterator( array_.begin( i, dims... ), scalar_ ); + } + //********************************************************************************************** + + //**End function******************************************************************************** + /*!\brief Returns an iterator just past the last non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator just past the last non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator end( size_t i, Dims... dims ) const { + return ConstIterator( array_.end(i, dims...), scalar_ ); + } + //********************************************************************************************** + + //**Num_dimensions function******************************************************************************* + /*!\brief Returns the current number of dimensions of the array. + // + // \return The number of rows of the array. + */ + inline static constexpr size_t num_dimensions() noexcept { + return RemoveCV_t>::num_dimensions(); + } + //********************************************************************************************** + + //**Dimensions function**************************************************************************** + /*!\brief Returns the current dimensions of the array. + // + // \return The dimensions of the array. + */ + inline decltype(auto) dimensions() const noexcept { + return array_.dimensions(); + } + //********************************************************************************************** + + //**Dimension function**************************************************************************** + /*!\brief Returns the current number of columns of the array. + // + // \return The number of columns of the array. + */ + template< size_t Dim > + inline size_t dimension() const noexcept { + return array_.template dimension(); + } + //********************************************************************************************** + + //**Left operand access************************************************************************* + /*!\brief Returns the left-hand side dense array operand. + // + // \return The left-hand side dense array operand. + */ + inline LeftOperand leftOperand() const noexcept { + return array_; + } + //********************************************************************************************** + + //**Right operand access************************************************************************ + /*!\brief Returns the right-hand side scalar operand. + // + // \return The right-hand side scalar operand. + */ + inline RightOperand rightOperand() const noexcept { + return scalar_; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can alias with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case the expression can alias, \a false otherwise. + */ + template< typename T > + inline bool canAlias( const T* alias ) const noexcept { + return IsExpression_v && array_.canAlias( alias ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression is aliased with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case an alias effect is detected, \a false otherwise. + */ + template< typename T > + inline bool isAliased( const T* alias ) const noexcept { + return array_.isAliased( alias ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the operands of the expression are properly aligned in memory. + // + // \return \a true in case the operands are aligned, \a false if not. + */ + inline bool isAligned() const noexcept { + return array_.isAligned(); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can be used in SMP assignments. + // + // \return \a true in case the expression can be used in SMP assignments, \a false if not. + */ + inline bool canSMPAssign() const noexcept { + return array_.canSMPAssign() || + ( dimension<0>() * dimension<1>() >= SMP_DMATSCALARMULT_THRESHOLD ); + } + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + LeftOperand array_; //!< Left-hand side dense array of the division expression. + RightOperand scalar_; //!< Right-hand side scalar of the division expression. + //********************************************************************************************** + + //**Assignment to dense matrices**************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a dense array-scalar + // division expression to a dense array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the array + // operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + assign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + assign( ~lhs, rhs.array_ ); + assign( ~lhs, (~lhs) / rhs.scalar_ ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to dense matrices******************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief Addition assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression to be added. + // \return void + // + // This function implements the performance optimized addition assignment of a dense array- + // scalar division expression to a dense array. Due to the explicit application of the + // SFINAE principle, this function can only be selected by the compiler in case the array + // operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + addAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( serial( rhs ) ); + addAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to sparse matrices****************************************************** + // No special implementation for the addition assignment to sparse matrices. + //********************************************************************************************** + + //**Subtraction assignment to dense matrices**************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Subtraction assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression to be subtracted. + // \return void + // + // This function implements the performance optimized subtraction assignment of a dense array- + // scalar division expression to a dense array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the array operand is + // a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + subAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( serial( rhs ) ); + subAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Subtraction assignment to sparse matrices*************************************************** + // No special implementation for the subtraction assignment to sparse matrices. + //********************************************************************************************** + + //**Schur product assignment to dense matrices************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Schur product assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression for the Schur product. + // \return void + // + // This function implements the performance optimized Schur product assignment of a dense + // array-scalar division expression to a dense array. Due to the explicit application of + // the SFINAE principle, this function can only be selected by the compiler in case the + // array operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + schurAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( serial( rhs ) ); + schurAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to dense matrices************************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a dense array-scalar + // division expression to a dense array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression + // specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + smpAssign( ~lhs, rhs.array_ ); + smpAssign( ~lhs, (~lhs) / rhs.scalar_ ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP addition assignment to dense matrices*************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP addition assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression to be added. + // \return void + // + // This function implements the performance optimized SMP addition assignment of a dense + // array-scalar division expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case + // the expression specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAddAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( rhs ); + smpAddAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP subtraction assignment to dense matrices************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP subtraction assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression to be subtracted. + // \return void + // + // This function implements the performance optimized SMP subtraction assignment of a dense + // array-scalar division expression to a dense array. Due to the explicit application of + // the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSubAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( rhs ); + smpSubAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP Schur product assignment to dense matrices********************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP Schur product assignment of a dense array-scalar division to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side division expression for the Schur product. + // \return void + // + // This function implements the performance optimized SMP Schur product assignment of a dense + // array-scalar division expression to a dense array. Due to the explicit application of the + // SFINAE principle, this function can only be selected by the compiler in case the expression + // specific parallel evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSchurAssign( DenseArray& lhs, const DArrScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( rhs ); + smpSchurAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST ); + BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ST ); + BLAZE_CONSTRAINT_MUST_NOT_BE_FLOATING_POINT_TYPE( ElementType ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL BINARY ARITHMETIC OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the dense array/scalar division operator. +// \ingroup math_traits +*/ +template< typename MT // Type of the left-hand side dense array + , typename ST > // Type of the right-hand side scalar +struct DArrScalarDivExprHelper +{ + private: + //********************************************************************************************** + using ScalarType = If_t< IsFloatingPoint_v< UnderlyingBuiltin_t > || + IsFloatingPoint_v< UnderlyingBuiltin_t > + , If_t< IsComplex_v< UnderlyingNumeric_t > && IsBuiltin_v + , DivTrait_t< UnderlyingBuiltin_t, ST > + , DivTrait_t< UnderlyingNumeric_t, ST > > + , ST >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_t< IsInvertible_v + , DArrScalarMultExpr + , DArrScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Division operator for the division of a dense array by a scalar value (\f$ A=B/s \f$). +// \ingroup dense_array +// +// \param mat The left-hand side dense array for the division. +// \param scalar The right-hand side scalar value for the division. +// \return The scaled result array. +// +// This operator represents the division of a dense array by a scalar value: + + \code + blaze::DynamicMatrix A, B; + // ... Resizing and initialization + B = A / 0.24; + \endcode + +// The operator returns an expression representing a dense array of the higher-order element +// type of the involved data types \a MT::ElementType and \a ST. Note that this operator only +// works for scalar values of built-in data type. +// +// \note A division by zero is only checked by an user assert. +*/ +template< typename MT // Type of the left-hand side dense array + , typename ST // Type of the right-hand side scalar + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) operator/( const DenseArray& mat, ST scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != ST(0), "Division by zero detected" ); + + using ReturnType = typename DArrScalarDivExprHelper::Type; + using ScalarType = RightOperand_t; + + if( IsMultExpr_v ) { + return ReturnType( ~mat, ScalarType(1)/ScalarType(scalar) ); + } + else { + return ReturnType( ~mat, scalar ); + } +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense array-scalar division +// expression and a scalar value (\f$ A=(B/s1)*s2 \f$). +// \ingroup dense_array +// +// \param mat The left-hand side dense array-scalar division. +// \param scalar The right-hand side scalar value for the multiplication. +// \return The scaled result array. +// +// This operator implements a performance optimized treatment of the multiplication of a +// dense array-scalar division expression and a scalar value. +*/ +template< typename MT // Type of the dense array of the left-hand side expression + , typename ST1 // Type of the scalar of the left-hand side expression + , typename ST2 // Type of the right-hand side scalar + , EnableIf_t< IsNumeric_v && ( IsInvertible_v || IsInvertible_v ) >* = nullptr > +inline decltype(auto) operator*( const DArrScalarDivExpr& mat, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return mat.leftOperand() * ( scalar / mat.rightOperand() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a scalar value and a dense array- +// scalar division expression (\f$ A=s2*(B/s1) \f$). +// \ingroup dense_array +// +// \param scalar The left-hand side scalar value for the multiplication. +// \param mat The right-hand side dense array-scalar division. +// \return The scaled result array. +// +// This operator implements a performance optimized treatment of the multiplication of a +// scalar value and a dense array-scalar division expression. +*/ +template< typename ST1 // Type of the left-hand side scalar + , typename MT // Type of the dense array of the right-hand side expression + , typename ST2 // Type of the scalar of the right-hand side expression + , EnableIf_t< IsNumeric_v && ( IsInvertible_v || IsInvertible_v ) >* = nullptr > +inline decltype(auto) operator*( ST1 scalar, const DArrScalarDivExpr& mat ) +{ + BLAZE_FUNCTION_TRACE; + + return mat.leftOperand() * ( scalar / mat.rightOperand() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Division operator for the division of a dense array-scalar division expression +// and a scalar value (\f$ A=(B/s1)/s2 \f$). +// \ingroup dense_array +// +// \param mat The left-hand side dense array-scalar division. +// \param scalar The right-hand side scalar value for the division. +// \return The scaled result array. +// +// This operator implements a performance optimized treatment of the division of a dense +// array-scalar division expression and a scalar value. +*/ +template< typename MT // Type of the dense array of the left-hand side expression + , typename ST1 // Type of the scalar of the left-hand side expression + , typename ST2 // Type of the right-hand side scalar + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) operator/( const DArrScalarDivExpr& mat, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" ); + + using MultType = MultTrait_t; + using ReturnType = typename DArrScalarDivExprHelper::Type; + using ScalarType = RightOperand_t; + + if( IsMultExpr_v ) { + return ReturnType( mat.leftOperand(), ScalarType(1)/( mat.rightOperand() * scalar ) ); + } + else { + return ReturnType( mat.leftOperand(), mat.rightOperand() * scalar ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsAligned< DArrScalarDivExpr > + : public IsAligned +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsPadded< DArrScalarDivExpr > + : public IsPadded +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsSymmetric< DArrScalarDivExpr > + : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsHermitian< DArrScalarDivExpr > + : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsLower< DArrScalarDivExpr > + : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsStrictlyLower< DArrScalarDivExpr > + : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsUpper< DArrScalarDivExpr > + : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsStrictlyUpper< DArrScalarDivExpr > + : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrScalarMultExpr.h b/blaze_tensor/math/expressions/DArrScalarMultExpr.h new file mode 100644 index 0000000..fcece02 --- /dev/null +++ b/blaze_tensor/math/expressions/DArrScalarMultExpr.h @@ -0,0 +1,1418 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/DArrScalarMultExpr.h +// \brief Header file for the dense array/scalar multiplication expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_ARRAY_MATH_EXPRESSIONS_DARRSCALARMULTEXPR_H_ +#define _BLAZE_ARRAY_MATH_EXPRESSIONS_DARRSCALARMULTEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DARRSCALARMULTEXPR +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Expression object for dense array-scalar multiplications. +// \ingroup dense_array_expression +// +// The DArrScalarMultExpr class represents the compile time expression for multiplications between +// a dense array and a scalar value. +*/ +template< typename MT // Type of the left-hand side dense array + , typename ST > // Type of the right-hand side scalar value +class DArrScalarMultExpr + : public ArrScalarMultExpr< DenseArray< DArrScalarMultExpr > > + , private Computation +{ + private: + //**Type definitions**************************************************************************** + using RT = ResultType_t; //!< Result type of the dense array expression. + using RN = ReturnType_t; //!< Return type of the dense array expression. + using ET = ElementType_t; //!< Element type of the dense array expression. + using CT = CompositeType_t; //!< Composite type of the dense array expression. + //********************************************************************************************** + + //**Return type evaluation********************************************************************** + //! Compilation switch for the selection of the subscript operator return type. + /*! The \a returnExpr compile time constant expression is a compilation switch for the + selection of the \a ReturnType. If the array operand returns a temporary vector + or array, \a returnExpr will be set to \a false and the subscript operator will + return it's result by value. Otherwise \a returnExpr will be set to \a true and + the subscript operator may return it's result as an expression. */ + static constexpr bool returnExpr = !IsTemporary_v; + + //! Expression return type for the subscript operator. + using ExprReturnType = decltype( std::declval() * std::declval() ); + //********************************************************************************************** + + //**Serial evaluation strategy****************************************************************** + //! Compilation switch for the serial evaluation strategy of the multiplication expression. + /*! The \a useAssign compile time constant expression represents a compilation switch for + the serial evaluation strategy of the multiplication expression. In case the given dense + array expression of type \a MT is a computation expression and requires an intermediate + evaluation, \a useAssign will be set to 1 and the multiplication expression will be + evaluated via the \a assign function family. Otherwise \a useAssign will be set to 0 + and the expression will be evaluated via the subscript operator. */ + static constexpr bool useAssign = ( IsComputation_v && RequiresEvaluation_v ); + + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool UseAssign_v = useAssign; + /*! \endcond */ + //********************************************************************************************** + + //**Parallel evaluation strategy**************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + /*! This variable template is a helper for the selection of the parallel evaluation strategy. + In case either the target array or the dense array operand is not SMP assignable and the + array operand is a computation expression that requires an intermediate evaluation, the + variable is set to 1 and the expression specific evaluation strategy is selected. Otherwise + the variable is set to 0 and the default strategy is chosen. */ + template< typename MT2 > + static constexpr bool UseSMPAssign_v = + ( ( !MT2::smpAssignable || !MT::smpAssignable ) && useAssign ); + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + using This = DArrScalarMultExpr; //!< Type of this DArrScalarMultExpr instance. + using ResultType = MultTrait_t; //!< Result type for expression template evaluations. + using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Resulting element type. + + //! Return type for expression template evaluations. + using ReturnType = const If_t< returnExpr, ExprReturnType, ElementType >; + + //! Data type for composite expression templates. + using CompositeType = If_t< useAssign, const ResultType, const DArrScalarMultExpr& >; + + //! Composite type of the left-hand side dense array expression. + using LeftOperand = If_t< IsExpression_v, const MT, const MT& >; + + //! Composite type of the right-hand side scalar value. + using RightOperand = ST; + //********************************************************************************************** + + //**ConstIterator class definition************************************************************** + /*!\brief Iterator over the elements of the dense array. + */ + class ConstIterator + { + public: + //**Type definitions************************************************************************* + using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. + using ValueType = ElementType; //!< Type of the underlying elements. + using PointerType = ElementType*; //!< Pointer return type. + using ReferenceType = ElementType&; //!< Reference return type. + using DifferenceType = ptrdiff_t; //!< Difference between two iterators. + + // STL iterator requirements + using iterator_category = IteratorCategory; //!< The iterator category. + using value_type = ValueType; //!< Type of the underlying elements. + using pointer = PointerType; //!< Pointer return type. + using reference = ReferenceType; //!< Reference return type. + using difference_type = DifferenceType; //!< Difference between two iterators. + + //! ConstIterator type of the dense array expression. + using IteratorType = ConstIterator_t; + //******************************************************************************************* + + //**Constructor****************************************************************************** + /*!\brief Constructor for the ConstIterator class. + // + // \param iterator Iterator to the initial element. + // \param scalar Scalar of the multiplication expression. + */ + explicit inline ConstIterator( IteratorType iterator, RightOperand scalar ) + : iterator_( iterator ) // Iterator to the current element + , scalar_ ( scalar ) // Scalar of the multiplication expression + {} + //******************************************************************************************* + + //**Addition assignment operator************************************************************* + /*!\brief Addition assignment operator. + // + // \param inc The increment of the iterator. + // \return The incremented iterator. + */ + inline ConstIterator& operator+=( size_t inc ) { + iterator_ += inc; + return *this; + } + //******************************************************************************************* + + //**Subtraction assignment operator********************************************************** + /*!\brief Subtraction assignment operator. + // + // \param dec The decrement of the iterator. + // \return The decremented iterator. + */ + inline ConstIterator& operator-=( size_t dec ) { + iterator_ -= dec; + return *this; + } + //******************************************************************************************* + + //**Prefix increment operator**************************************************************** + /*!\brief Pre-increment operator. + // + // \return Reference to the incremented iterator. + */ + inline ConstIterator& operator++() { + ++iterator_; + return *this; + } + //******************************************************************************************* + + //**Postfix increment operator*************************************************************** + /*!\brief Post-increment operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator++( int ) { + return ConstIterator( iterator_++ ); + } + //******************************************************************************************* + + //**Prefix decrement operator**************************************************************** + /*!\brief Pre-decrement operator. + // + // \return Reference to the decremented iterator. + */ + inline ConstIterator& operator--() { + --iterator_; + return *this; + } + //******************************************************************************************* + + //**Postfix decrement operator*************************************************************** + /*!\brief Post-decrement operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator--( int ) { + return ConstIterator( iterator_-- ); + } + //******************************************************************************************* + + //**Element access operator****************************************************************** + /*!\brief Direct access to the element at the current iterator position. + // + // \return The resulting value. + */ + inline ReturnType operator*() const { + return *iterator_ * scalar_; + } + //******************************************************************************************* + + //**Load function**************************************************************************** + /*!\brief Access to the SIMD elements of the array. + // + // \return The resulting SIMD element. + */ + inline auto load() const noexcept { + return iterator_.load() * set( scalar_ ); + } + //******************************************************************************************* + + //**Equality operator************************************************************************ + /*!\brief Equality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators refer to the same element, \a false if not. + */ + inline bool operator==( const ConstIterator& rhs ) const { + return iterator_ == rhs.iterator_; + } + //******************************************************************************************* + + //**Inequality operator********************************************************************** + /*!\brief Inequality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators don't refer to the same element, \a false if they do. + */ + inline bool operator!=( const ConstIterator& rhs ) const { + return iterator_ != rhs.iterator_; + } + //******************************************************************************************* + + //**Less-than operator*********************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller, \a false if not. + */ + inline bool operator<( const ConstIterator& rhs ) const { + return iterator_ < rhs.iterator_; + } + //******************************************************************************************* + + //**Greater-than operator******************************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater, \a false if not. + */ + inline bool operator>( const ConstIterator& rhs ) const { + return iterator_ > rhs.iterator_; + } + //******************************************************************************************* + + //**Less-or-equal-than operator************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. + */ + inline bool operator<=( const ConstIterator& rhs ) const { + return iterator_ <= rhs.iterator_; + } + //******************************************************************************************* + + //**Greater-or-equal-than operator*********************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater or equal, \a false if not. + */ + inline bool operator>=( const ConstIterator& rhs ) const { + return iterator_ >= rhs.iterator_; + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Calculating the number of elements between two iterators. + // + // \param rhs The right-hand side iterator. + // \return The number of elements between the two iterators. + */ + inline DifferenceType operator-( const ConstIterator& rhs ) const { + return iterator_ - rhs.iterator_; + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between a ConstIterator and an integral value. + // + // \param it The iterator to be incremented. + // \param inc The number of elements the iterator is incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { + return ConstIterator( it.iterator_ + inc, it.scalar_ ); + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between an integral value and a ConstIterator. + // + // \param inc The number of elements the iterator is incremented. + // \param it The iterator to be incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { + return ConstIterator( it.iterator_ + inc, it.scalar_ ); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Subtraction between a ConstIterator and an integral value. + // + // \param it The iterator to be decremented. + // \param dec The number of elements the iterator is decremented. + // \return The decremented iterator. + */ + friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { + return ConstIterator( it.iterator_ - dec, it.scalar_ ); + } + //******************************************************************************************* + + private: + //**Member variables************************************************************************* + IteratorType iterator_; //!< Iterator to the current element. + RightOperand scalar_; //!< Scalar of the multiplication expression. + //******************************************************************************************* + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = + ( MT::simdEnabled && IsNumeric_v && + ( HasSIMDMult_v || HasSIMDMult_v,ST> ) ); + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = MT::smpAssignable; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + //**Constructor********************************************************************************* + /*!\brief Constructor for the DArrScalarMultExpr class. + // + // \param array The left-hand side dense array of the multiplication expression. + // \param scalar The right-hand side scalar of the multiplication expression. + */ + explicit inline DArrScalarMultExpr( const MT& array, ST scalar ) noexcept + : array_( array ) // Left-hand side dense array of the multiplication expression + , scalar_( scalar ) // Right-hand side scalar of the multiplication expression + {} + //********************************************************************************************** + + //**Access operator***************************************************************************** + /*!\brief 2D-access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + */ + template< typename... Dims > + inline ReturnType operator()( Dims... dims ) const { + return array_( dims... ) * scalar_; + } + //********************************************************************************************** + + //**At function********************************************************************************* + /*!\brief Checked access to the array elements. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + // \exception std::out_of_range Invalid array access index. + */ + template< typename... Dims > + inline ReturnType at( Dims... dims ) const { + return ( *this )( dims... ); + } + //********************************************************************************************** + + //**Load function******************************************************************************* + /*!\brief Access to the SIMD elements of the array. + // + // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. + // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. + // \return Reference to the accessed values. + */ + template< typename... Dims > + BLAZE_ALWAYS_INLINE auto load( Dims... dims ) const noexcept { + return array_.load( dims... ) * set( scalar_ ); + } + //********************************************************************************************** + + //**Begin function****************************************************************************** + /*!\brief Returns an iterator to the first non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator to the first non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator begin( size_t i, Dims... dims ) const { + return ConstIterator( array_.begin( i, dims... ), scalar_ ); + } + //********************************************************************************************** + + //**End function******************************************************************************** + /*!\brief Returns an iterator just past the last non-zero element of row \a i. + // + // \param i The row index. + // \return Iterator just past the last non-zero element of row \a i. + */ + template< typename... Dims > + inline ConstIterator end( size_t i, Dims... dims ) const { + return ConstIterator( array_.end(i, dims...), scalar_ ); + } + //********************************************************************************************** + + //**Num_dimensions function******************************************************************************* + /*!\brief Returns the current number of dimensions of the array. + // + // \return The number of rows of the array. + */ + inline static constexpr size_t num_dimensions() noexcept { + return RemoveCV_t>::num_dimensions(); + } + //********************************************************************************************** + + //**Dimensions function**************************************************************************** + /*!\brief Returns the current dimensions of the array. + // + // \return The dimensions of the array. + */ + inline decltype(auto) dimensions() const noexcept { + return array_.dimensions(); + } + //********************************************************************************************** + + //**Dimension function**************************************************************************** + /*!\brief Returns the current number of columns of the array. + // + // \return The number of columns of the array. + */ + template< size_t Dim > + inline size_t dimension() const noexcept { + return array_.template dimension(); + } + //********************************************************************************************** + + //**Left operand access************************************************************************* + /*!\brief Returns the left-hand side dense array operand. + // + // \return The left-hand side dense array operand. + */ + inline LeftOperand leftOperand() const noexcept { + return array_; + } + //********************************************************************************************** + + //**Right operand access************************************************************************ + /*!\brief Returns the right-hand side scalar operand. + // + // \return The right-hand side scalar operand. + */ + inline RightOperand rightOperand() const noexcept { + return scalar_; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can alias with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case the expression can alias, \a false otherwise. + */ + template< typename T > + inline bool canAlias( const T* alias ) const noexcept { + return IsExpression_v && array_.canAlias( alias ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression is aliased with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case an alias effect is detected, \a false otherwise. + */ + template< typename T > + inline bool isAliased( const T* alias ) const noexcept { + return array_.isAliased( alias ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the operands of the expression are properly aligned in memory. + // + // \return \a true in case the operands are aligned, \a false if not. + */ + inline bool isAligned() const noexcept { + return array_.isAligned(); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can be used in SMP assignments. + // + // \return \a true in case the expression can be used in SMP assignments, \a false if not. + */ + inline bool canSMPAssign() const noexcept { + return array_.canSMPAssign() || + ( dimension<0>() * dimension<1>() >= SMP_DMATSCALARMULT_THRESHOLD ); + } + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + LeftOperand array_; //!< Left-hand side dense array of the multiplication expression. + RightOperand scalar_; //!< Right-hand side scalar of the multiplication expression. + //********************************************************************************************** + + //**Assignment to dense matrices**************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a dense array-scalar + // multiplication expression to a dense array. Due to the explicit application of the + // SFINAE principle, this function can only be selected by the compiler in case the array + // operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + assign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + assign( ~lhs, rhs.array_ ); + assign( ~lhs, (~lhs) * rhs.scalar_ ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to dense matrices******************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief Addition assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression to be added. + // \return void + // + // This function implements the performance optimized addition assignment of a dense array- + // scalar multiplication expression to a dense array. Due to the explicit application of + // the SFINAE principle, this function can only be selected by the compiler in case the + // array operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + addAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( serial( rhs ) ); + addAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Subtraction assignment to dense matrices**************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Subtraction assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression to be subtracted. + // \return void + // + // This function implements the performance optimized subtraction assignment of a dense array- + // scalar multiplication expression to a dense array. Due to the explicit application of the + // SFINAE principle, this function can only be selected by the compiler in case the array + // operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + subAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( serial( rhs ) ); + subAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Schur product assignment to dense matrices************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Schur product assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression for the Schur product. + // \return void + // + // This function implements the performance optimized Schur product assignment of a dense + // array-scalar multiplication expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // array operand is a computation expression and requires an intermediate evaluation. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseAssign_v > + schurAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( serial( rhs ) ); + schurAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to dense matrices************************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a dense array-scalar + // multiplication expression to a dense array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression + // specific evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + smpAssign( ~lhs, rhs.array_ ); + smpAssign( ~lhs, (~lhs) * rhs.scalar_ ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP addition assignment to dense matrices*************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP addition assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression to be added. + // \return void + // + // This function implements the performance optimized SMP addition assignment of a dense + // array-scalar multiplication expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpAddAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( rhs ); + smpAddAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP subtraction assignment to dense matrices************************************************ + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP subtraction assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression to be subtracted. + // \return void + // + // This function implements the performance optimized SMP subtraction assignment of a dense + // array-scalar multiplication expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSubAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( rhs ); + smpSubAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP Schur product assignment to dense matrices********************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP Schur product assignment of a dense array-scalar multiplication to a dense array. + // \ingroup dense_array + // + // \param lhs The target left-hand side dense array. + // \param rhs The right-hand side multiplication expression for the Schur product. + // \return void + // + // This function implements the performance optimized SMP Schur product assignment of a dense + // array-scalar multiplication expression to a dense array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific evaluation strategy is selected. + */ + template< typename MT2 > // Type of the target dense array + friend inline EnableIf_t< UseSMPAssign_v > + smpSchurAssign( DenseArray& lhs, const DArrScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + + BLAZE_INTERNAL_ASSERT( ( ~lhs ).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const ResultType tmp( rhs ); + smpSchurAssign( ~lhs, tmp ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ST ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ST, RightOperand ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL UNARY ARITHMETIC OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Unary minus operator for the negation of a dense array (\f$ A = -B \f$). +// \ingroup dense_array +// +// \param dm The dense array to be negated. +// \return The negation of the array. +// +// This operator represents the negation of a dense array: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = -A; + \endcode + +// The operator returns an expression representing the negation of the given dense array. +*/ +template< typename MT > // Type of the target dense array +inline decltype(auto) operator-( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ScalarType = UnderlyingBuiltin_t; + using ReturnType = const DArrScalarMultExpr; + return ReturnType( ~dm, ScalarType(-1) ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL BINARY ARITHMETIC OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Multiplication operator for the multiplication of a dense array and a scalar value +// (\f$ A=B*s \f$). +// \ingroup dense_array +// +// \param mat The left-hand side dense array for the multiplication. +// \param scalar The right-hand side scalar value for the multiplication. +// \return The scaled result array. +// +// This operator represents the multiplication between a dense array and a scalar value: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = A * 1.25; + \endcode + +// The operator returns an expression representing a dense array of the higher-order element +// type of the involved data types \a MT::ElementType and \a ST. Note that this operator only +// works for scalar values of built-in data type. +*/ +template< typename MT // Type of the left-hand side dense array + , typename ST // Type of the right-hand side scalar + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) operator*( const DenseArray& mat, ST scalar ) +{ + BLAZE_FUNCTION_TRACE; + + using ScalarType = MultTrait_t< UnderlyingBuiltin_t, ST >; + using ReturnType = const DArrScalarMultExpr; + return ReturnType( ~mat, scalar ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Multiplication operator for the multiplication of a scalar value and a dense array +// (\f$ A=s*B \f$). +// \ingroup dense_array +// +// \param scalar The left-hand side scalar value for the multiplication. +// \param mat The right-hand side dense array for the multiplication. +// \return The scaled result array. +// +// This operator represents the multiplication between a a scalar value and dense array: + + \code + blaze::DynamicArray A, B; + // ... Resizing and initialization + B = 1.25 * A; + \endcode + +// The operator returns an expression representing a dense array of the higher-order element +// type of the involved data types \a ST and \a MT::ElementType. Note that this operator only +// works for scalar values of built-in data type. +*/ +template< typename ST // Type of the left-hand side scalar + , typename MT // Type of the right-hand side dense array + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) operator*( ST scalar, const DenseArray& mat ) +{ + BLAZE_FUNCTION_TRACE; + + using ScalarType = MultTrait_t< ST, UnderlyingBuiltin_t >; + using ReturnType = const DArrScalarMultExpr; + return ReturnType( ~mat, scalar ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING UNARY ARITHMETIC OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Unary minus operator for the negation of a dense array-scalar multiplication +// (\f$ A = -(B*s) \f$). +// \ingroup dense_array +// +// \param dm The dense array-scalar multiplication to be negated. +// \return The negation of the dense array-scalar multiplication. +// +// This operator implements a performance optimized treatment of the negation of a dense array- +// scalar multiplication expression. +*/ +template< typename MT // Type of the dense array + , typename ST > // Type of the scalar +inline decltype(auto) operator-( const DArrScalarMultExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const DArrScalarMultExpr; + return ReturnType( dm.leftOperand(), -dm.rightOperand() ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense array-scalar multiplication +// expression and a scalar value (\f$ A=(B*s1)*s2 \f$). +// \ingroup dense_array +// +// \param mat The left-hand side dense array-scalar multiplication. +// \param scalar The right-hand side scalar value for the multiplication. +// \return The scaled result array. +// +// This operator implements a performance optimized treatment of the multiplication of a +// dense array-scalar multiplication expression and a scalar value. +*/ +template< typename MT // Type of the dense array of the left-hand side expression + , typename ST1 // Type of the scalar of the left-hand side expression + , typename ST2 // Type of the right-hand side scalar + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) operator*( const DArrScalarMultExpr& mat, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return mat.leftOperand() * ( mat.rightOperand() * scalar ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a scalar value and a dense array- +// scalar multiplication expression (\f$ A=s2*(B*s1) \f$). +// \ingroup dense_array +// +// \param scalar The left-hand side scalar value for the multiplication. +// \param mat The right-hand side dense array-scalar multiplication. +// \return The scaled result array. +// +// This operator implements a performance optimized treatment of the multiplication of a +// scalar value and a dense array-scalar multiplication expression. +*/ +template< typename ST1 // Type of the left-hand side scalar + , typename MT // Type of the dense array of the right-hand side expression + , typename ST2 // Type of the scalar of the right-hand side expression + , EnableIf_t< IsNumeric_v >* = nullptr > +inline decltype(auto) operator*( ST1 scalar, const DArrScalarMultExpr& mat ) +{ + BLAZE_FUNCTION_TRACE; + + return mat.leftOperand() * ( scalar * mat.rightOperand() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Division operator for the division of a dense array-scalar multiplication +// expression by a scalar value (\f$ A=(B*s1)/s2 \f$). +// \ingroup dense_array +// +// \param mat The left-hand side dense array-scalar multiplication. +// \param scalar The right-hand side scalar value for the division. +// \return The scaled result array. +// +// This operator implements a performance optimized treatment of the division of a +// dense array-scalar multiplication expression by a scalar value. +*/ +template< typename MT // Type of the dense array of the left-hand side expression + , typename ST1 // Type of the scalar of the left-hand side expression + , typename ST2 // Type of the right-hand side scalar + , EnableIf_t< IsNumeric_v && ( IsInvertible_v || IsInvertible_v ) >* = nullptr > +inline decltype(auto) operator/( const DArrScalarMultExpr& mat, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return mat.leftOperand() * ( mat.rightOperand() / scalar ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense array-scalar +// multiplication expression and a dense vector (\f$ \vec{a}=(B*s1)*\vec{c} \f$). +// \ingroup dense_vector +// +// \param mat The left-hand side dense array-scalar multiplication. +// \param vec The right-hand side dense vector. +// \return The scaled result vector. +// +// This operator implements the performance optimized treatment of the multiplication of a +// dense array-scalar multiplication and a dense vector. It restructures the expression +// \f$ \vec{a}=(B*s1)*\vec{c} \f$ to the expression \f$ \vec{a}=(B*\vec{c})*s1 \f$. +*/ +// template< typename MT // Type of the dense array of the left-hand side expression +// , typename ST // Type of the scalar of the left-hand side expression +// , typename VT > // Type of the right-hand side dense vector +// inline decltype(auto) +// operator*( const DArrScalarMultExpr& mat, const DenseVector& vec ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return ( mat.leftOperand() * (~vec) ) * mat.rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense vector and a dense +// array-scalar multiplication expression (\f$ \vec{a}^T=\vec{c}^T*(B*s1) \f$). +// \ingroup dense_vector +// +// \param vec The left-hand side dense vector. +// \param mat The right-hand side dense array-scalar multiplication. +// \return The scaled result vector. +// +// This operator implements the performance optimized treatment of the multiplication of a +// dense vector and a dense array-scalar multiplication. It restructures the expression +// \f$ \vec{a}=\vec{c}^T*(B*s1) \f$ to the expression \f$ \vec{a}^T=(\vec{c}^T*B)*s1 \f$. +*/ +// template< typename VT // Type of the left-hand side dense vector +// , typename MT // Type of the dense array of the right-hand side expression +// , typename ST > // Type of the scalar of the right-hand side expression +// inline decltype(auto) +// operator*( const DenseVector& vec, const DArrScalarMultExpr& mat ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return ( (~vec) * mat.leftOperand() ) * mat.rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense array-scalar +// multiplication expression and a dense vector-scalar multiplication expression +// (\f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$). +// \ingroup dense_vector +// +// \param mat The left-hand side dense array-scalar multiplication. +// \param vec The right-hand side dense vector-scalar multiplication. +// \return The scaled result vector. +// +// This operator implements the performance optimized treatment of the multiplication +// of a dense array-scalar multiplication and a dense vector-scalar multiplication. It +// restructures the expression \f$ \vec{a}=(B*s1)*(\vec{c}*s2) \f$ to the expression +// \f$ \vec{a}=(B*\vec{c})*(s1*s2) \f$. +*/ +// template< typename MT // Type of the dense array of the left-hand side expression +// , typename ST1 // Type of the scalar of the left-hand side expression +// , typename VT // Type of the dense vector of the right-hand side expression +// , typename ST2 > // Type of the scalar of the right-hand side expression +// inline decltype(auto) +// operator*( const DArrScalarMultExpr& mat, const DVecScalarMultExpr& vec ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return ( mat.leftOperand() * vec.leftOperand() ) * ( mat.rightOperand() * vec.rightOperand() ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense vector-scalar +// multiplication expression and a dense array-scalar multiplication expression +// (\f$ \vec{a}^T=\vec{b}^T*(C*s1) \f$). +// \ingroup dense_vector +// +// \param vec The left-hand side dense vector-scalar multiplication. +// \param mat The right-hand side dense array-scalar multiplication. +// \return The scaled result vector. +// +// This operator implements the performance optimized treatment of the multiplication +// of a dense vector-scalar multiplication and a dense array-scalar multiplication. It +// restructures the expression \f$ \vec{a}=(\vec{b}^T*s1)*(C*s2) \f$ to the expression +// \f$ \vec{a}^T=(\vec{b}^T*C)*(s1*s2) \f$. +*/ +// template< typename VT // Type of the dense vector of the left-hand side expression +// , typename ST1 // Type of the scalar of the left-hand side expression +// , typename MT // Type of the dense array of the right-hand side expression +// , typename ST2 > // Type of the scalar of the right-hand side expression +// inline decltype(auto) +// operator*( const DVecScalarMultExpr& vec, const DArrScalarMultExpr& mat ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return ( vec.leftOperand() * mat.leftOperand() ) * ( vec.rightOperand() * mat.rightOperand() ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense array-scalar multiplication +// expression and a dense array (\f$ A=(B*s1)*C \f$). +// \ingroup dense_array +// +// \param lhs The left-hand side dense array-scalar multiplication. +// \param rhs The right-hand side dense array. +// \return The scaled result array. +// +// This operator implements the performance optimized treatment of the multiplication of a +// dense array-scalar multiplication and a dense array. It restructures the expression +// \f$ A=(B*s1)*C \f$ to the expression \f$ A=(B*C)*s1 \f$. +*/ +template< typename MT1 // Type of the dense array of the left-hand side expression + , typename ST // Type of the scalar of the left-hand side expression + , typename MT2 > // Type of the right-hand side dense array +inline decltype(auto) + operator*( const DArrScalarMultExpr& lhs, const DenseArray& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( lhs.leftOperand() * (~rhs) ) * lhs.rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of a dense array and a dense array- +// scalar multiplication expression (\f$ A=(B*s1)*C \f$). +// \ingroup dense_array +// +// \param lhs The left-hand side dense array. +// \param rhs The right-hand side dense array-scalar multiplication. +// \return The scaled result array. +// +// This operator implements the performance optimized treatment of the multiplication of a +// dense array and a dense array-scalar multiplication. It restructures the expression +// \f$ A=B*(C*s1) \f$ to the expression \f$ A=(B*C)*s1 \f$. +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 // Type of the dense array of the right-hand side expression + , typename ST > // Type of the scalar of the right-hand side expression +inline decltype(auto) + operator*( const DenseArray& lhs, const DArrScalarMultExpr& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( (~lhs) * rhs.leftOperand() ) * rhs.rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Multiplication operator for the multiplication of two dense array-scalar multiplication +// expressions (\f$ A=(B*s1)*(C*s2) \f$). +// \ingroup dense_array +// +// \param lhs The left-hand side dense array-scalar multiplication. +// \param rhs The right-hand side dense array-scalar multiplication. +// \return The scaled result array. +// +// This operator implements the performance optimized treatment of the multiplication of +// two dense array-scalar multiplication expressions. It restructures the expression +// \f$ A=(B*s1)*(C*s2) \f$ to the expression \f$ A=(B*C)*(s1*s2) \f$. +*/ +template< typename MT1 // Type of the dense array of the left-hand side expression + , typename ST1 // Type of the scalar of the left-hand side expression + , typename MT2 // Type of the right-hand side dense array + , typename ST2 > // Type of the scalar of the right-hand side expression +inline decltype(auto) + operator*( const DArrScalarMultExpr& lhs, const DArrScalarMultExpr& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( lhs.leftOperand() * rhs.leftOperand() ) * ( lhs.rightOperand() * rhs.rightOperand() ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsAligned< DArrScalarMultExpr > + : public IsAligned +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsPadded< DArrScalarMultExpr > + : public IsPadded +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsSymmetric< DArrScalarMultExpr > + : public IsSymmetric +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsHermitian< DArrScalarMultExpr > + : public IsHermitian +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsLower< DArrScalarMultExpr > + : public IsLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsStrictlyLower< DArrScalarMultExpr > + : public IsStrictlyLower +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsUpper< DArrScalarMultExpr > + : public IsUpper +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST > +struct IsStrictlyUpper< DArrScalarMultExpr > + : public IsStrictlyUpper +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DenseArray.h b/blaze_tensor/math/expressions/DenseArray.h new file mode 100644 index 0000000..d609e3f --- /dev/null +++ b/blaze_tensor/math/expressions/DenseArray.h @@ -0,0 +1,250 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/DenseArray.h +// \brief Header file for the DenseArray base class +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include + +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\defgroup dense_array Dense Arrays +// \ingroup array +*/ +/*!\defgroup dense_array_expression Expressions +// \ingroup dense_array +*/ +/*!\brief Base class for dense arrays. +// \ingroup dense_array +// +// The DenseArray class is a base class for all dense array classes. It provides an +// abstraction from the actual type of the dense array, but enables a conversion back +// to this type via the Array base class. +*/ +template< typename TT > // Type of the dense array +struct DenseArray + : public Array +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseArray global functions */ +//@{ +template< typename TT > +BLAZE_ALWAYS_INLINE typename TT::ElementType* data( DenseArray& dm ) noexcept; + +template< typename TT > +BLAZE_ALWAYS_INLINE typename TT::ElementType* data( const DenseArray& dm ) noexcept; + +template< typename TT > +BLAZE_ALWAYS_INLINE size_t spacing( const DenseArray& dm ) noexcept; +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c data() function for arrays without mutable data access. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return Pointer to the internal element storage. +// +// This function returns the internal storage of a dense array without mutable data access, +// which is represented by \c nullptr. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE DisableIf_t< HasMutableDataAccess_v, typename TT::ElementType* > + data_backend( DenseArray& dm ) noexcept +{ + MAYBE_UNUSED( dm ); + + return nullptr; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c data() function for arrays with mutable data access. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return Pointer to the internal element storage. +// +// This function returns the internal storage of a dense array with mutable data access. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE EnableIf_t< HasMutableDataAccess_v, typename TT::ElementType* > + data_backend( DenseArray& dm ) noexcept +{ + return (~dm).data(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the dense array elements. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return Pointer to the internal element storage. +// +// This function provides a unified interface to access the given dense array's internal +// element storage. In contrast to the \c data() member function, which is only available +// in case the array has some internal storage, this function can be used on all kinds of +// dense arrays. In case the given dense array does not provide low-level data access, +// the function returns \c nullptr. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE typename TT::ElementType* data( DenseArray& dm ) noexcept +{ + return data_backend( ~dm ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c data() function for arrays without constant data access. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return Pointer to the internal element storage. +// +// This function returns the internal storage of a dense array without constant data access, +// which is represented by \c nullptr. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE DisableIf_t< HasConstDataAccess_v, typename TT::ElementType* > + data_backend( const DenseArray& dm ) noexcept +{ + MAYBE_UNUSED( dm ); + + return nullptr; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation of the \c data() function for arrays with constant data access. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return Pointer to the internal element storage. +// +// This function returns the internal storage of a dense array with constant data access. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE EnableIf_t< HasConstDataAccess_v, typename TT::ElementType* > + data_backend( const DenseArray& dm ) noexcept +{ + return (~dm).data(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the dense array elements. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return Pointer to the internal element storage. +// +// This function provides a unified interface to access the given dense array's internal +// element storage. In contrast to the \c data() member function, which is only available +// in case the array has some internal storage, this function can be used on all kinds of +// dense arrays. In case the given dense array does not provide low-level data access, +// the function returns \c nullptr. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE typename TT::ElementType* data( const DenseArray& dm ) noexcept +{ + return data_backend( ~dm ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the spacing between the beginning of two rows/columns. +// \ingroup dense_array +// +// \param dm The given array. +// \return The spacing between the beginning of two rows/columns. +*/ +template< typename TT > // Type of the array +BLAZE_ALWAYS_INLINE size_t spacing( const DenseArray& dm ) noexcept +{ + return (~dm).spacing(); +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/Forward.h b/blaze_tensor/math/expressions/Forward.h index 11f116c..644ecf6 100644 --- a/blaze_tensor/math/expressions/Forward.h +++ b/blaze_tensor/math/expressions/Forward.h @@ -51,7 +51,10 @@ namespace blaze { // //================================================================================================= +template< typename > struct DenseArray; + template< typename > struct DenseTensor; + template< typename > class DTensSerialExpr; template< typename, typename, bool > class DTensDMatSchurExpr; template< typename, typename > class DTensDTensAddExpr; @@ -60,7 +63,7 @@ template< typename, typename > class DTensDTensSchurExpr; template< typename, typename > class DTensDTensSubExpr; template< typename, typename > class DTensDVecMultExpr; template< typename, typename > class DTensMapExpr; -//template< typename > class DTensRavelExpr; +template< typename > class DTensRavelExpr; template< typename, typename > class DTensScalarMultExpr; template< typename, typename > class DTensScalarDivExpr; template< typename, typename, typename > class DTensDTensMapExpr; @@ -69,6 +72,10 @@ template< typename, size_t... > class DTensTransExpr; template< typename, size_t... > class DMatExpandExpr; template< typename > class DMatRavelExpr; +template< typename, typename > class DArrMapExpr; +template< typename, typename, typename > class DArrDArrMapExpr; +template< typename, typename > class DArrScalarMultExpr; +template< typename, typename > class DArrScalarDivExpr; template< typename TT1, typename TT2 > @@ -115,6 +122,9 @@ decltype(auto) map( const DenseTensor&, const DenseTensor&, OP ); template< typename TT, typename OP > decltype(auto) reduce( const DenseTensor&, OP ); +template< typename TT, typename OP > +decltype(auto) reduce( const DenseArray&, OP ); + template< typename TT, bool SO > decltype(auto) expand( const DenseMatrix&, size_t ); @@ -127,8 +137,8 @@ decltype(auto) expand( const DenseMatrix&, size_t ); template< typename MT, bool SO > decltype(auto) ravel( const DenseMatrix& ); -//template< typename TT > -//decltype(auto) ravel( const DenseTensor& ); +template< typename TT > +decltype(auto) ravel( const DenseTensor& ); } // namespace blaze diff --git a/blaze_tensor/math/smp/ArrayThreadMapping.h b/blaze_tensor/math/smp/ArrayThreadMapping.h new file mode 100644 index 0000000..42c94a1 --- /dev/null +++ b/blaze_tensor/math/smp/ArrayThreadMapping.h @@ -0,0 +1,113 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/smp/ArrayThreadMapping.h +// \brief Header file for the SMP thread mapping functionality +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_SMP_ARRAYTHREADMAPPING_H_ +#define _BLAZE_TENSOR_MATH_SMP_ARRAYTHREADMAPPING_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace blaze { + +//================================================================================================= +// +// THREADMAPPING FUNCTIONALITY +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creates a 3D mapping of threads. +// \ingroup smp +// +// \param threads The total number of threads to be mapped. +// \param A The tensor the mapping is created for. +// \return 2D mapping of the given number of threads. +// +// This function creates a 2D mapping of the given number of threads for the given tensor \a A. +// The mapping will depend on the ratio between rows and columns of the tensor and its storage +// order. +*/ +template< typename MT >// Type of the tensor +ThreadMapping createThreadMapping( size_t threads, const Array& A ) +{ + const size_t M( (~A).dimension<1>() ); + const size_t N( (~A).dimension<0>() ); + + if( M > N ) + { + const double ratio( double(M)/double(N) ); + size_t m = min( threads, max( 1UL, static_cast( round( sqrt( threads*ratio ) ) ) ) ); + size_t n = threads / m; + + while( m * n != threads ) { + ++m; + n = threads / m; + } + + return ThreadMapping( m, n ); + } + else + { + const double ratio( double(N)/double(M) ); + size_t n = min( threads, max( 1UL, static_cast( round( sqrt( threads*ratio ) ) ) ) ); + size_t m = threads / n; + + while( m * n != threads ) { + ++n; + m = threads / n; + } + + return ThreadMapping( m, n ); + } +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/smp/DenseArray.h b/blaze_tensor/math/smp/DenseArray.h new file mode 100644 index 0000000..b846b92 --- /dev/null +++ b/blaze_tensor/math/smp/DenseArray.h @@ -0,0 +1,57 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/smp/DenseArray.h +// \brief Header file for the dense array SMP implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_SMP_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_SMP_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + +#if BLAZE_HPX_PARALLEL_MODE +#include +#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE +#include +#elif BLAZE_OPENMP_PARALLEL_MODE +#include +#else +#include +#endif + +#endif diff --git a/blaze_tensor/math/smp/default/DenseArray.h b/blaze_tensor/math/smp/default/DenseArray.h new file mode 100644 index 0000000..1dba1d5 --- /dev/null +++ b/blaze_tensor/math/smp/default/DenseArray.h @@ -0,0 +1,257 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/smp/default/DenseArray.h +// \brief Header file for the default dense array SMP implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_SMP_DEFAULT_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_SMP_DEFAULT_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include + +#include +#include + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Dense array SMP functions */ +//@{ +template< typename TT1, typename TT2 > +inline EnableIf_t< IsDenseArray_v > + smpAssign( Array& lhs, const Array& rhs ); + +template< typename TT1, typename TT2 > +inline EnableIf_t< IsDenseArray_v > + smpAddAssign( Array& lhs, const Array& rhs ); + +template< typename TT1, typename TT2 > +inline EnableIf_t< IsDenseArray_v > + smpSubAssign( Array& lhs, const Array& rhs ); + +template< typename TT1, typename TT2 > +inline EnableIf_t< IsDenseArray_v > + smpSchurAssign( Array& lhs, const Array& rhs ); +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Default implementation of the SMP assignment of a array to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be assigned. +// \return void +// +// This function implements the default SMP assignment of a array to a dense array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v > + smpAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions(), "Invalid dimensions" ); + + assign( ~lhs, ~rhs ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Default implementation of the SMP addition assignment of a array to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be added. +// \return void +// +// This function implements the default SMP addition assignment of a array to a dense array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v > + smpAddAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions(), "Invalid dimensions" ); + + addAssign( ~lhs, ~rhs ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Default implementation of the SMP subtraction assignment of a array to dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be subtracted. +// \return void +// +// This function implements the default SMP subtraction assignment of a array to a dense array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v > + smpSubAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions(), "Invalid dimensions" ); + + subAssign( ~lhs, ~rhs ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Default implementation of the SMP Schur product assignment of a array to dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array for the Schur product. +// \return void +// +// This function implements the default SMP Schur product assignment of a array to a dense +// array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v > + smpSchurAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions(), "Invalid dimensions" ); + + schurAssign( ~lhs, ~rhs ); +} +//************************************************************************************************* + + +//================================================================================================= +// +// MULTIPLICATION ASSIGNMENT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the SMP multiplication assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be multiplied. +// \return void +// +// This function implements the default HPX-based SMP multiplication assignment to a dense +// array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT1 // Type of the left-hand side dense array + , typename AT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v > + smpMultAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions(), "Invalid dimensions" ); + + multAssign( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + + + + +//================================================================================================= +// +// COMPILE TIME CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +namespace { + +BLAZE_STATIC_ASSERT( !BLAZE_HPX_PARALLEL_MODE ); +BLAZE_STATIC_ASSERT( !BLAZE_CPP_THREADS_PARALLEL_MODE ); +BLAZE_STATIC_ASSERT( !BLAZE_BOOST_THREADS_PARALLEL_MODE ); +BLAZE_STATIC_ASSERT( !BLAZE_OPENMP_PARALLEL_MODE ); + +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/smp/hpx/DenseArray.h b/blaze_tensor/math/smp/hpx/DenseArray.h new file mode 100644 index 0000000..fb385fc --- /dev/null +++ b/blaze_tensor/math/smp/hpx/DenseArray.h @@ -0,0 +1,568 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/smp/hpx/DenseArray.h +// \brief Header file for the HPX-based dense array SMP implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_SMP_HPX_DENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_SMP_HPX_DENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// #include + +namespace blaze { + +//================================================================================================= +// +// HPX-BASED ASSIGNMENT KERNELS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend of the HPX-based SMP (compound) assignment of a dense array to a dense array. +// \ingroup math +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side dense array to be assigned. +// \param op The (compound) assignment operation. +// \return void +// +// This function is the backend implementation of the HPX-based SMP assignment of a dense +// array to a dense array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 // Type of the right-hand side dense array + , typename OP > // Type of the assignment operation +void hpxAssign( DenseArray& lhs, const DenseArray& rhs, OP op ) +{ + using hpx::parallel::for_loop; + using hpx::parallel::execution::par; + + BLAZE_FUNCTION_TRACE; + + using ET1 = ElementType_t; + using ET2 = ElementType_t; + + constexpr bool simdEnabled( TT1::simdEnabled && TT2::simdEnabled && IsSIMDCombinable_v ); + constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t >::size ); + + const bool lhsAligned( (~lhs).isAligned() ); + const bool rhsAligned( (~rhs).isAligned() ); + + const size_t rows = (~rhs).template dimension<1>(); + const size_t columns = (~rhs).template dimension<0>(); + + const size_t threads ( getNumThreads() ); + const size_t numRows ( min( static_cast( BLAZE_HPX_MATRIX_BLOCK_SIZE_ROW ), rows ) ); + const size_t numCols ( min( static_cast( BLAZE_HPX_MATRIX_BLOCK_SIZE_COLUMN ), columns ) ); + + const size_t rowsPerIter( numRows ); + const size_t addon1 ( ( ( rows % rowsPerIter ) != 0UL )? 1UL : 0UL ); + const size_t equalShare1( rows / rowsPerIter + addon1 ); + + const size_t rest2 ( numCols & ( SIMDSIZE - 1UL ) ); + const size_t colsPerIter( ( simdEnabled && rest2 )?( numCols - rest2 + SIMDSIZE ):( numCols ) ); + const size_t addon2 ( ( ( columns % colsPerIter ) != 0UL )? 1UL : 0UL ); + const size_t equalShare2( columns / colsPerIter + addon2 ); + + hpx::parallel::execution::dynamic_chunk_size chunkSize ( BLAZE_HPX_MATRIX_CHUNK_SIZE ); + + for_loop( par.with( chunkSize ), size_t(0), equalShare1 * equalShare2, [&](int i) + { + const size_t row ( ( i / equalShare2 ) * rowsPerIter ); + const size_t column( ( i % equalShare2 ) * colsPerIter ); + + if( row >= rows || column >= columns ) + return; + +// for (size_t k = 0; k != (~rhs).pages(); ++k) +// { +// const size_t m( min( rowsPerIter, rows - row ) ); +// const size_t n( min( colsPerIter, columns - column ) ); +// +// auto lhs_slice = pageslice( ~lhs, k ); +// auto rhs_slice = pageslice( ~rhs, k ); +// +// if( simdEnabled && lhsAligned && rhsAligned ) { +// auto target( submatrix ( ~lhs_slice, row, column, m, n ) ); +// const auto source( submatrix ( ~rhs_slice, row, column, m, n ) ); +// op( target, source ); +// } +// else if( simdEnabled && lhsAligned ) { +// auto target( submatrix ( ~lhs_slice, row, column, m, n ) ); +// const auto source( submatrix( ~rhs_slice, row, column, m, n ) ); +// op( target, source ); +// } +// else if( simdEnabled && rhsAligned ) { +// auto target( submatrix( ~lhs_slice, row, column, m, n ) ); +// const auto source( submatrix ( ~rhs_slice, row, column, m, n ) ); +// op( target, source ); +// } +// else { +// auto target(submatrix(~lhs_slice, row, column, m, n )); +// const auto source(submatrix(~rhs_slice, row, column, m, n )); +// op(target, source); +// } +// } + } ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// PLAIN ASSIGNMENT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the HPX-based SMP assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be assigned. +// \return void +// +// This function implements the default HPX-based SMP assignment to a dense array. Due to +// the explicit application of the SFINAE principle, this function can only be selected by the +// compiler in case both operands are SMP-assignable and the element types of both operands are +// not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && ( !IsSMPAssignable_v || !IsSMPAssignable_v ) > + smpAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + assign( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Implementation of the HPX-based SMP assignment to a dense array. +// \ingroup math +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be assigned. +// \return void +// +// This function implements the HPX-based SMP assignment to a dense array. Due to the +// explicit application of the SFINAE principle, this function can only be selected by the +// compiler in case both operands are SMP-assignable and the element types of both operands +// are not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && IsSMPAssignable_v && IsSMPAssignable_v > + smpAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) { + assign( ~lhs, ~rhs ); + } + else { + hpxAssign( ~lhs, ~rhs, Assign() ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDITION ASSIGNMENT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the HPX-based SMP addition assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be added. +// \return void +// +// This function implements the default HPX-based SMP addition assignment to a dense array. +// Due to the explicit application of the SFINAE principle, this function can only be selected +// by the compiler in case both operands are SMP-assignable and the element types of both operands +// are not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && ( !IsSMPAssignable_v || !IsSMPAssignable_v ) > + smpAddAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + addAssign( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Implementation of the HPX-based SMP addition assignment to a dense array. +// \ingroup math +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be added. +// \return void +// +// This function implements the HPX-based SMP addition assignment to a dense array. Due to +// the explicit application of the SFINAE principle, this function can only be selected by the +// compiler in case both operands are SMP-assignable and the element types of both operands are +// not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && IsSMPAssignable_v && IsSMPAssignable_v > + smpAddAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) { + addAssign( ~lhs, ~rhs ); + } + else { + hpxAssign( ~lhs, ~rhs, AddAssign() ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRACTION ASSIGNMENT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the HPX-based SMP subtracction assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be subtracted. +// \return void +// +// This function implements the default HPX-based SMP subtraction assignment to a dense array. +// Due to the explicit application of the SFINAE principle, this function can only be selected by +// the compiler in case both operands are SMP-assignable and the element types of both operands +// are not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && ( !IsSMPAssignable_v || !IsSMPAssignable_v ) > + smpSubAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + subAssign( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Implementation of the HPX-based SMP subtracction assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be subtracted. +// \return void +// +// This function implements the default HPX-based SMP subtraction assignment of a array to a +// dense array. Due to the explicit application of the SFINAE principle, this function can only +// be selected by the compiler in case both operands are SMP-assignable and the element types of +// both operands are not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && IsSMPAssignable_v && IsSMPAssignable_v > + smpSubAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) { + subAssign( ~lhs, ~rhs ); + } + else { + hpxAssign( ~lhs, ~rhs, SubAssign() ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SCHUR PRODUCT ASSIGNMENT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the HPX-based SMP Schur product assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array for the Schur product. +// \return void +// +// This function implements the default HPX-based SMP Schur product assignment to a dense +// array. Due to the explicit application of the SFINAE principle, this function can only be +// selected by the compiler in case both operands are SMP-assignable and the element types of +// both operands are not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && ( !IsSMPAssignable_v || !IsSMPAssignable_v ) > + smpSchurAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + schurAssign( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Implementation of the HPX-based SMP Schur product assignment to a dense array. +// \ingroup math +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array for the Schur product. +// \return void +// +// This function implements the HPX-based SMP Schur product assignment to a dense array. Due +// to the explicit application of the SFINAE principle, this function can only be selected by the +// compiler in case both operands are SMP-assignable and the element types of both operands are +// not SMP-assignable.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v && IsSMPAssignable_v && IsSMPAssignable_v > + smpSchurAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t ); + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) { + schurAssign( ~lhs, ~rhs ); + } + else { + hpxAssign( ~lhs, ~rhs, SchurAssign() ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTIPLICATION ASSIGNMENT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the HPX-based SMP multiplication assignment to a dense array. +// \ingroup smp +// +// \param lhs The target left-hand side dense array. +// \param rhs The right-hand side array to be multiplied. +// \return void +// +// This function implements the default HPX-based SMP multiplication assignment to a dense +// array.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename TT1 // Type of the left-hand side dense array + , typename TT2 > // Type of the right-hand side array +inline EnableIf_t< IsDenseArray_v > + smpMultAssign( Array& lhs, const Array& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == (~rhs).dimensions() , "Invalid array sizes" ); + + multAssign( ~lhs, ~rhs ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COMPILE TIME CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +namespace { + +BLAZE_STATIC_ASSERT( BLAZE_HPX_PARALLEL_MODE ); + +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsArray.h b/blaze_tensor/math/typetraits/IsArray.h new file mode 100644 index 0000000..2316e1a --- /dev/null +++ b/blaze_tensor/math/typetraits/IsArray.h @@ -0,0 +1,129 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/typetraits/IsArray.h +// \brief Header file for the IsArray type trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAY_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the IsArray type trait. +// \ingroup math_type_traits +*/ +template< typename T > +struct IsArrayHelper +{ + private: + //********************************************************************************************** + template< typename MT > + static TrueType test( const Array& ); + + template< typename MT > + static TrueType test( const volatile Array& ); + + static FalseType test( ... ); + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = decltype( test( std::declval() ) ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time check for array types. +// \ingroup math_type_traits +// +// This type trait tests whether or not the given template parameter is a N-dimensional dense +// or sparse array type. In case the type is a array type, the \a value member constant is +// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives +// from \a TrueType. Otherwise \a yes is set to \a false, \a Type is \a FalseType, and the +// class derives from \a FalseType. + + \code + blaze::IsArray< const DynamicArray >::Type // Results in TrueType + blaze::IsArray< StaticVector >::value // Evaluates to 0 + blaze::IsArray< const DynamicVector >::Type // Results in FalseType + blaze::IsArray< volatile CompressedVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsArray + : public IsArrayHelper::Type +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary variable template for the IsArray type trait. +// \ingroup type_traits +// +// The IsArray_v variable template provides a convenient shortcut to access the nested \a value +// of the IsArray class template. For instance, given the type \a T the following two statements +// are identical: + + \code + constexpr bool value1 = blaze::IsArray::value; + constexpr bool value2 = blaze::IsArray_v; + \endcode +*/ +template< typename T > +constexpr bool IsArray_v = IsArray::value; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsDenseArray.h b/blaze_tensor/math/typetraits/IsDenseArray.h new file mode 100644 index 0000000..322e490 --- /dev/null +++ b/blaze_tensor/math/typetraits/IsDenseArray.h @@ -0,0 +1,131 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/typetraits/IsDenseArray.h +// \brief Header file for the IsDenseArray type trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISDENSEARRAY_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISDENSEARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the IsDenseArray type trait. +// \ingroup math_type_traits +*/ +template< typename T > +struct IsDenseArrayHelper +{ + private: + //********************************************************************************************** + template< typename MT > + static TrueType test( const DenseArray& ); + + template< typename MT > + static TrueType test( const volatile DenseArray& ); + + static FalseType test( ... ); + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = decltype( test( std::declval() ) ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time check for dense array types. +// \ingroup math_type_traits +// +// This type trait tests whether or not the given template parameter is a dense, N-dimensional +// array type. In case the type is a dense array type, the \a value member constant is set +// to \a true, the nested type definition \a Type is \a TrueType, and the class derives from +// \a TrueType. Otherwise \a yes is set to \a false, \a Type is \a FalseType, and the class +// derives from \a FalseType. + + \code + blaze::IsDenseArray< DynamicArray >::value // Evaluates to 1 + blaze::IsDenseArray< const DynamicArray >::Type // Results in TrueType + blaze::IsDenseArray< volatile DynamicArray > // Is derived from TrueType + blaze::IsDenseArray< CompressedMatrix::value // Evaluates to 0 + blaze::IsDenseArray< CompressedVector >::Type // Results in FalseType + blaze::IsDenseArray< DynamicVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsDenseArray + : public IsDenseArrayHelper::Type +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary variable template for the IsDenseArray type trait. +// \ingroup type_traits +// +// The IsDenseArray_v variable template provides a convenient shortcut to access the nested +// \a value of the IsDenseArray class template. For instance, given the type \a T the +// following two statements are identical: + + \code + constexpr bool value1 = blaze::IsDenseArray::value; + constexpr bool value2 = blaze::IsDenseArray_v; + \endcode +*/ +template< typename T > +constexpr bool IsDenseArray_v = IsDenseArray::value; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsRowMajorArray.h b/blaze_tensor/math/typetraits/IsRowMajorArray.h new file mode 100644 index 0000000..618edde --- /dev/null +++ b/blaze_tensor/math/typetraits/IsRowMajorArray.h @@ -0,0 +1,138 @@ +//================================================================================================= +/*! +// \file blaze/math/typetraits/IsRowMajorArray.h +// \brief Header file for the IsRowMajorArray type trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISROWMAJORARRAY_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISROWMAJORARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the IsRowMajorArray type trait. +// \ingroup math_type_traits +*/ +template< typename T > +struct IsRowMajorArrayHelper +{ + private: + //********************************************************************************************** + template< typename MT > + static TrueType test( const Array& ); + + template< typename MT > + static TrueType test( const volatile Array& ); + + static FalseType test( ... ); + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = decltype( test( std::declval() ) ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time check for row-major matrix types. +// \ingroup math_type_traits +// +// This type trait tests whether or not the given template argument is a row-major dense or +// sparse matrix type (i.e., a matrix whose storage order is set to \a true). In case the type +// is a row-major matrix type, the \a value member constant is set to \a true, the nested type +// definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise \a value +// is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. + + \code + using blaze::StaticArray; + using blaze::DynamicArray; + using blaze::CompressedArray; + using blaze::rowMajor; + using blaze::columnMajor; + + blaze::IsRowMajorArray< StaticArray >::value // Evaluates to 1 + blaze::IsRowMajorArray< const DynamicArray >::Type // Results in TrueType + blaze::IsRowMajorArray< volatile CompressedArray > // Is derived from TrueType + blaze::IsRowMajorArray< StaticArray >::value // Evaluates to 0 + blaze::IsRowMajorArray< const DynamicArray >::Type // Results in FalseType + blaze::IsRowMajorArray< volatile CompressedArray > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsRowMajorArray + : public IsRowMajorArrayHelper::Type +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary variable template for the IsRowMajorArray type trait. +// \ingroup type_traits +// +// The IsRowMajorArray_v variable template provides a convenient shortcut to access the nested +// \a value of the IsRowMajorArray class template. For instance, given the type \a T the +// following two statements are identical: + + \code + constexpr bool value1 = blaze::IsRowMajorArray::value; + constexpr bool value2 = blaze::IsRowMajorArray_v; + \endcode +*/ +template< typename T > +constexpr bool IsRowMajorArray_v = IsRowMajorArray::value; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/util/ArrayForEach.h b/blaze_tensor/util/ArrayForEach.h new file mode 100644 index 0000000..f420098 --- /dev/null +++ b/blaze_tensor/util/ArrayForEach.h @@ -0,0 +1,455 @@ +//================================================================================================= +/*! +// \file blaze/util/ArrayForEach.h +// \brief Header file for the ArrayForEach function +// +// Copyright (C) 2012-2019 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_UTIL_ARRAYFOREACH_H_ +#define _BLAZE_TENSOR_UTIL_ARRAYFOREACH_H_ + +#include +#include + +#include + +namespace blaze { + +template< size_t Shift = 1, size_t N > +std::array< size_t, N - Shift > ArrayShift( std::array< size_t, N > const& dims ) +{ + BLAZE_STATIC_ASSERT(N >= 2 && N > Shift); // cannot shift more than elements + + std::array result; + for( size_t i = 0; i != N - Shift; ++i ) { + result[i] = dims[i]; + } + return result; +} + +//************************************************************************************************* +/*!\brief ArrayForEach function to iterate over arbitrary dimension data. +// \ingroup util +*/ +// N == 4 +// +// for( size_t c = 0UL; c < l_; ++c ) { +// size_t x1 = ( c + 0 ) * o_; +// +// N == 3 +// for( size_t k = 0UL; k < o_; ++k ) { +// size_t x2 = ( x1 + k ) * m_; +// +// N == 2 +// for( size_t i = 0UL; i < m_; ++i ) { +// size_t x3 = ( x2 + i ) * nn_; +// +// N == 1 +// for( size_t j = n_; j < n_; ++j ) { +// size_t x4 = ( x3 + j ); +// v_[x4] = Type(); +// } +// } +// } +// } +// +template< typename F > +void ArrayForEach( + std::array< size_t, 1 > const& dims, F const& f, size_t base = 0 ) +{ + for( size_t i = 0; i != dims[0]; ++i ) { + f( i + base ); + } +} + +template< size_t N, typename F > +void ArrayForEach( + std::array< size_t, N > const& dims, F const& f, size_t base = 0 ) +{ + BLAZE_STATIC_ASSERT( N >= 2 ); + std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j) { + ArrayForEach( shifted_dims, f, i ); + } +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief ArrayForEachPadded function to iterate over arbitrary dimension data. +// \ingroup util +*/ +// N == 4 +// +// for( size_t c = 0UL; c < l_; ++c ) { +// size_t x1 = ( c + 0 ) * o_; +// +// N == 3 +// for( size_t k = 0UL; k < o_; ++k ) { +// size_t x2 = ( x1 + k ) * m_; +// +// N == 2 +// for( size_t i = 0UL; i < m_; ++i ) { +// size_t x3 = ( x2 + i ) * nn_; +// +// N == 1 +// for( size_t j = n_; j < nn_; ++j ) { +// size_t x4 = ( x3 + j ); +// v_[x4] = Type(); +// } +// } +// } +// } +// +template< typename F > +void ArrayForEachPadded( + std::array< size_t, 1 > const& dims, size_t nn, F const& f, size_t base = 0 ) +{ + for( size_t i = dims[0]; i != nn; ++i ) { + f( i + base ); + } +} + +template< size_t N, typename F > +void ArrayForEachPadded( + std::array< size_t, 2 > const& dims, size_t nn, F const& f, size_t base = 0 ) +{ + std::array< size_t, 1 > shifted_dims = ArrayShift( dims ); + for( size_t i = base * nn, j = 0; j != dims[1]; i += nn, ++j ) { + ArrayForEachPadded( shifted_dims, nn, f, i ); + } +} + +template< size_t N, typename F > +void ArrayForEachPadded( + std::array< size_t, N > const& dims, size_t nn, F const& f, size_t base = 0 ) +{ + BLAZE_STATIC_ASSERT( N >= 2 ); + std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j ) { + ArrayForEachPadded( shifted_dims, nn, f, i ); + } +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief ArrayForEachGrouped function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< typename F, size_t M > +void ArrayForEachGrouped( + size_t dim0, F const& f, std::array< size_t, M >& currdims ) +{ + for( currdims[0] = 0; currdims[0] != dim0; ++currdims[0] ) { + f( currdims ); + } +} + +template< typename F, size_t M > +void ArrayForEachGrouped( + std::array< size_t, 2 > const& dims, F const& f, std::array< size_t, M >& currdims ) +{ + for( currdims[1] = 0; currdims[1] != dims[1]; ++currdims[1] ) { + ArrayForEachGrouped( dims[0], f, currdims ); + } +} + +template< size_t N, typename F, size_t M > +void ArrayForEachGrouped( + std::array< size_t, N > const& dims, F const& f, std::array< size_t, M >& currdims ) +{ + BLAZE_STATIC_ASSERT( N > 2 ); + std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + for( currdims[N - 1] = 0; currdims[N - 1] != dims[N - 1]; ++currdims[N - 1] ) { + ArrayForEachGrouped( shifted_dims, f, currdims ); + } +} + +template< size_t N, typename F > +void ArrayForEachGrouped( + std::array< size_t, N > const& dims, F const& f ) +{ + std::array< size_t, N > currdims{}; + ArrayForEachGrouped( dims, f, currdims ); +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief ArrayForEachGrouped function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< typename F, size_t M > +void ArrayForEachGrouped( + size_t dim0, F const& f, std::array< size_t, M >& currdims, size_t base ) +{ + for( currdims[0] = 0; currdims[0] != dim0; ++currdims[0], ++base ) { + f( base, currdims ); + } +} + +template< typename F, size_t M > +void ArrayForEachGrouped( + std::array< size_t, 2 > const& dims, size_t nn, F const& f, std::array< size_t, M >& currdims, size_t base = 0 ) +{ + std::array< size_t, 1 > shifted_dims = ArrayShift( dims ); + currdims[1] = 0; + for( size_t i = base * nn; currdims[1] != dims[1]; i += nn, ++currdims[1]) { + ArrayForEachGrouped( dims[0], f, currdims, i ); + } +} + +template< size_t N, typename F, size_t M > +void ArrayForEachGrouped( + std::array< size_t, N > const& dims, size_t nn, F const& f, std::array< size_t, M >& currdims, size_t base = 0 ) +{ + BLAZE_STATIC_ASSERT( N > 2 ); + std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + currdims[N - 1] = 0; + for( size_t i = base * dims[N - 2]; currdims[N - 1] != dims[N - 1]; i += dims[N - 2], ++currdims[N - 1]) { + ArrayForEachGrouped( shifted_dims, nn, f, currdims, i ); + } +} + +template< size_t N, typename F > +void ArrayForEachGrouped( + std::array< size_t, N > const& dims, size_t nn, F const& f ) +{ + std::array< size_t, N > currdims{}; + ArrayForEachGrouped( dims, nn, f, currdims ); +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief ArrayForEach2 function to iterate over arbitrary dimension data. +// \ingroup util +*/ +// N == 4 +// +// for( size_t c = 0UL; c < l_; ++c ) { +// size_t x1 = ( c + 0 ) * o_; +// +// N == 3 +// for( size_t k = 0UL; k < o_; ++k ) { +// size_t x2 = ( x1 + k ) * m_; +// +// N == 2 +// for( size_t i = 0UL; i < m_; ++i ) { +// size_t x3 = ( x2 + i ) * nn_; +// size_t x31 = ( x2 + i ) * n_; +// +// N == 1 +// for( size_t j = n_; j < n_; ++j ) { +// v_[x3 + j] = array[x31 + j]; +// } +// } +// } +// } +// +template< typename F > +void ArrayForEach2( + size_t dim0, F const& f, size_t base1, size_t base2 ) +{ + for( size_t i = 0; i != dims[0]; ++i ) { + f( i + base1, i + base2 ); + } +} + +template< typename F > +void ArrayForEach2( + std::array< size_t, 2 > const& dims, size_t nn, F const& f, size_t base ) +{ + for( size_t i = 0; i != dims[1]; ++i ) { + size_t index1 = (i + base) * dims[0]; + size_t index2 = (i + base) * nn; + ArrayForEach2( dims[0], f, index1, index2 ); + } +} + +template< size_t N, typename F > +void ArrayForEach2( + std::array< size_t, N > const& dims, size_t nn, F const& f, size_t base = 0 ) +{ + BLAZE_STATIC_ASSERT( N > 2 ); + std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j ) { + ArrayForEach2( shifted_dims, nn, f, i ); + } +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief ArrayForEachGroupedAnyOf function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< typename F, size_t M > +bool ArrayForEachGroupedAnyOf( std::array< size_t, 1 > const& dims, F const& f, + std::array< size_t, M >& currdims ) +{ + while( currdims[0] != dims[0] ) { + if( f( currdims ) ) + return true; + ++currdims[0]; + } + return false; +} + +template< size_t N, typename F, size_t M > +bool ArrayForEachGroupedAnyOf( std::array< size_t, N > const& dims, F const& f, + std::array< size_t, M >& currdims ) +{ + while( currdims[N - 1] != dims[N - 1] ) { + currdims[N - 2] = 0; + if( ArrayForEachGroupedAnyOf( ArrayShift( dims ), f, currdims ) ) { + return true; + } + ++currdims[N - 1]; + } + return false; +} + +template< size_t N, typename F > +bool ArrayForEachGroupedAnyOf( + std::array< size_t, N > const& dims, F const& f ) +{ + BLAZE_STATIC_ASSERT( N >= 3 ); + std::array< size_t, N > currdims{}; + return ArrayForEachGroupedAnyOf( dims, f, currdims ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ArrayForEachGroupedAnyOf function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< typename F, size_t M > +bool ArrayForEachGroupedAllOf( std::array< size_t, 1 > const& dims, F const& f, + std::array< size_t, M >& currdims ) +{ + while( currdims[0] != dims[0] ) { + if( !f( currdims ) ) + return false; + ++currdims[0]; + } + return true; +} + +template< size_t N, typename F, size_t M > +bool ArrayForEachGroupedAllOf( std::array< size_t, N > const& dims, F const& f, + std::array< size_t, M >& currdims ) +{ + while( currdims[N - 1] != dims[N - 1] ) { + currdims[N - 2] = 0; + if( !ArrayForEachGroupedAllOf( ArrayShift( dims ), f, currdims ) ) { + return false; + } + ++currdims[N - 1]; + } + return true; +} + +template< size_t N, typename F > +bool ArrayForEachGroupedAllOf( + std::array< size_t, N > const& dims, F const& f ) +{ + BLAZE_STATIC_ASSERT( N >= 3 ); + std::array< size_t, N > currdims{}; + return ArrayForEachGroupedAllOf( dims, f, currdims ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ArrayDimForEach function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< size_t N, typename F > +void ArrayDimForEach( std::array< size_t, N > const& dims, F const& f) +{ + for( size_t i = 0; i < N; ++i ) { + f(i); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ArrayDimAnyOf function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< size_t N, typename F > +bool ArrayDimAnyOf( std::array< size_t, N > const& dims, F const& f) +{ + for( size_t i = 0; i < N; ++i ) { + if( f( dims[i] ) ) { + return true; + } + } + return false; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ArrayDimAllOf function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< size_t N, typename F > +bool ArrayDimAllOf( std::array< size_t, N > const& dims, F const& f) +{ + for( size_t i = 0; i < N; ++i ) { + if( !f( dims[i] ) ) { + return false; + } + } + return true; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ArrayDimNoneOf function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< size_t N, typename F > +bool ArrayDimNoneOf( std::array< size_t, N > const& dims, F const& f) +{ + for( size_t i = 0; i < N; ++i ) { + if( f( dims[i] ) ) { + return false; + } + } + return true; +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blazetest/blazetest/mathtest/densearray/GeneralTest.h b/blazetest/blazetest/mathtest/densearray/GeneralTest.h new file mode 100644 index 0000000..45a9418 --- /dev/null +++ b/blazetest/blazetest/mathtest/densearray/GeneralTest.h @@ -0,0 +1,385 @@ +//================================================================================================= +/*! +// \file blazetest/mathtest/densearray/GeneralTest.h +// \brief Header file for the general DenseArray operation test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZETEST_MATHTEST_DENSEARRAY_GENERALTEST_H_ +#define _BLAZETEST_MATHTEST_DENSEARRAY_GENERALTEST_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + + +namespace blazetest { + +namespace mathtest { + +namespace densearray { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Auxiliary class for tests of the DenseMatrix functionality. +// +// This class represents a test suite for the DenseMatrix functionality contained in the +// header file. It performs a series of runtime +// tests with general matrices. +*/ +class GeneralTest +{ + private: + //**Type definitions**************************************************************************** + using cplx = blaze::complex; //!< Complex element type. + //********************************************************************************************** + + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit GeneralTest(); + // No explicitly declared copy constructor. + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + // No explicitly declared destructor. + //********************************************************************************************** + + private: + //**Test functions****************************************************************************** + /*!\name Test functions */ + //@{ + void testIsNan(); +// void testIsSquare(); +// void testIsSymmetric(); +// void testIsHermitian(); + void testIsUniform(); +// void testIsLower(); +// void testIsUniLower(); +// void testIsStrictlyLower(); +// void testIsUpper(); +// void testIsUniUpper(); +// void testIsStrictlyUpper(); +// void testIsDiagonal(); +// void testIsIdentity(); + void testMinimum(); + void testMaximum(); + void testSoftmax(); +// void testTrace(); + void testL1Norm(); + void testL2Norm(); + void testL3Norm(); + void testL4Norm(); + void testLpNorm(); + + template< typename Type > + void checkRows( const Type& tensor, size_t expectedRows ) const; + + template< typename Type > + void checkColumns( const Type& tensor, size_t expectedColumns ) const; + + template< typename Type > + void checkPages( const Type& tensor, size_t expectedPages ) const; + + template< typename Type > + void checkCapacity( const Type& tensor, size_t minCapacity ) const; + + template< typename Type > + void checkNonZeros( const Type& tensor, size_t expectedNonZeros ) const; + + template< typename Type > + void checkNonZeros( const Type& tensor, size_t i, size_t k, size_t expectedNonZeros ) const; + //@} + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::string test_; //!< Label of the currently performed test. + //@} + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Checking the number of rows of the given dense tensor. +// +// \param tensor The dense tensor to be checked. +// \param expectedRows The expected number of rows of the dense tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of rows of the given dense tensor. In case the actual number +// of rows does not correspond to the given expected number of rows, a \a std::runtime_error +// exception is thrown. +*/ +template< typename Type > // Type of the dense tensor +void GeneralTest::checkRows( const Type& tensor, size_t expectedRows ) const +{ + if( tensor.template dimension<1>() != expectedRows ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of rows detected\n" + << " Details:\n" + << " Number of rows : " << tensor.template dimension<1>() << "\n" + << " Expected number of rows: " << expectedRows << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of columns of the given dense tensor. +// +// \param tensor The dense tensor to be checked. +// \param expectedRows The expected number of columns of the dense tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of columns of the given dense tensor. In case the +// actual number of columns does not correspond to the given expected number of columns, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense tensor +void GeneralTest::checkColumns( const Type& tensor, size_t expectedColumns ) const +{ + if( tensor.template dimension<0>() != expectedColumns ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of columns detected\n" + << " Details:\n" + << " Number of columns : " << tensor.template dimension<0>() << "\n" + << " Expected number of columns: " << expectedColumns << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of pages of the given dense tensor. +// +// \param tensor The dense tensor to be checked. +// \param expectedRows The expected number of pages of the dense tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of pages of the given dense tensor. In case the +// actual number of pages does not correspond to the given expected number of pages, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense tensor +void GeneralTest::checkPages( const Type& tensor, size_t expectedPages ) const +{ + if( tensor.template dimension<2>() != expectedPages ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of pages detected\n" + << " Details:\n" + << " Number of pages : " << tensor.template dimension<2>() << "\n" + << " Expected number of pages: " << expectedPages << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the capacity of the given dense tensor. +// +// \param tensor The dense tensor to be checked. +// \param minCapacity The expected minimum capacity of the dense tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the capacity of the given dense tensor. In case the actual capacity +// is smaller than the given expected minimum capacity, a \a std::runtime_error exception is +// thrown. +*/ +template< typename Type > // Type of the dense tensor +void GeneralTest::checkCapacity( const Type& tensor, size_t minCapacity ) const +{ + if( tensor.capacity() < minCapacity ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Capacity : " << tensor.capacity() << "\n" + << " Expected minimum capacity: " << minCapacity << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements of the given dense tensor. +// +// \param tensor The dense tensor to be checked. +// \param expectedNonZeros The expected number of non-zero elements of the dense tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements of the given dense tensor. In +// case the actual number of non-zero elements does not correspond to the given expected +// number, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense tensor +void GeneralTest::checkNonZeros( const Type& tensor, size_t expectedNonZeros ) const +{ + if( tensor.nonZeros() != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements\n" + << " Details:\n" + << " Number of non-zeros : " << tensor.nonZeros() << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( tensor.capacity() < tensor.nonZeros() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Number of non-zeros: " << tensor.nonZeros() << "\n" + << " Capacity : " << tensor.capacity() << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements in a specific row/column of the given dense tensor. +// +// \param tensor The dense tensor to be checked. +// \param index The row/column to be checked. +// \param expectedNonZeros The expected number of non-zero elements in the specified row/column. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements in the specified row/column of the +// given dense tensor. In case the actual number of non-zero elements does not correspond +// to the given expected number, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense tensor +void GeneralTest::checkNonZeros( const Type& tensor, size_t i, size_t k, size_t expectedNonZeros ) const +{ + if( tensor.nonZeros( i, k ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements in row " << i << " page " << k << "\n" + << " Details:\n" + << " Number of non-zeros : " << tensor.nonZeros( i, k ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( tensor.capacity( i, k ) < tensor.nonZeros( i, k ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected in row " << i << " page " << k << "\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( tensor, i, k ) << "\n" + << " Capacity : " << capacity( tensor, i, k ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Testing the functionality of the DenseMatrix class template. +// +// \return void +*/ +void runTest() +{ + GeneralTest(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// MACRO DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Macro for the execution of the general DenseMatrix operation test. +*/ +#define RUN_DENSEARRAY_GENERAL_TEST \ + blazetest::mathtest::densearray::runTest() +/*! \endcond */ +//************************************************************************************************* + +} // namespace densearray + +} // namespace mathtest + +} // namespace blazetest + +#endif diff --git a/blazetest/src/mathtest/CMakeLists.txt b/blazetest/src/mathtest/CMakeLists.txt index fde6fae..f1a1d68 100644 --- a/blazetest/src/mathtest/CMakeLists.txt +++ b/blazetest/src/mathtest/CMakeLists.txt @@ -33,6 +33,7 @@ set(subdirs columnslice customtensor + densearray densetensor dilatedsubmatrix dilatedsubvector diff --git a/blazetest/src/mathtest/densearray/CMakeLists.txt b/blazetest/src/mathtest/densearray/CMakeLists.txt new file mode 100644 index 0000000..300128d --- /dev/null +++ b/blazetest/src/mathtest/densearray/CMakeLists.txt @@ -0,0 +1,44 @@ +# ================================================================================================= +# +# Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +# Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +# +# This file is part of the Blaze library. You can redistribute it and/or modify it under +# the terms of the New (Revised) BSD License. Redistribution and use in source and binary +# forms, with or without modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# 3. Neither the names of the Blaze development group nor the names of its contributors +# may be used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# ================================================================================================= + + +set(category DenseArray) + +set(tests + GeneralTest +) + +foreach(test ${tests}) + add_blaze_tensor_test(${category}${test} + SOURCES ${test}.cpp + FOLDER "Tests/${category}") +endforeach() diff --git a/blazetest/src/mathtest/densearray/GeneralTest.cpp b/blazetest/src/mathtest/densearray/GeneralTest.cpp new file mode 100644 index 0000000..0388885 --- /dev/null +++ b/blazetest/src/mathtest/densearray/GeneralTest.cpp @@ -0,0 +1,3143 @@ +//================================================================================================= +/*! +// \file src/mathtest/densearray/GeneralTest.cpp +// \brief Source file for the general DenseArray operation test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + +#include +#include + +#include + +namespace blazetest { + +namespace mathtest { + +namespace densearray { + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constructor for the GeneralTest class test. +// +// \exception std::runtime_error Operation error detected. +*/ +GeneralTest::GeneralTest() +{ + testIsNan(); +// testIsSquare(); +// testIsSymmetric(); +// testIsHermitian(); +// testIsLower(); + testIsUniform(); +// testIsUniLower(); +// testIsStrictlyLower(); +// testIsUpper(); +// testIsUniUpper(); +// testIsStrictlyUpper(); +// testIsDiagonal(); +// testIsIdentity(); + testMinimum(); + testMaximum(); + testSoftmax(); +// testTrace(); + testL1Norm(); + testL2Norm(); + testL3Norm(); + testL4Norm(); + testLpNorm(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Test of the \c isnan() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isnan() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsNan() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "isnan()"; + + // isnan with 0x0 array + { + blaze::DynamicArray<3, float> arr; + + checkRows ( arr, 0UL ); + checkColumns ( arr, 0UL ); + checkPages ( arr, 0UL ); + checkNonZeros( arr, 0UL ); + + if( blaze::isnan( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isnan evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isnan with empty 3x5x7 array + { + blaze::DynamicArray<3, float> arr( blaze::init_from_value, 0.0F, 7UL, 3UL, 5UL ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 5UL ); + checkPages ( arr, 7UL ); + checkNonZeros( arr, 0UL ); + + if( blaze::isnan( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isnan evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isnan with filled 4x2x2 array + { + blaze::DynamicArray<3, float> arr( blaze::init_from_value, 0.0F, 2UL, 4UL, 2UL ); + arr(0,1,1) = 1.0F; + arr(0,2,0) = -2.0F; + arr(0,2,1) = 3.0F; + arr(0,3,0) = 4.0F; + + arr(1,1,1) = -1.0F; + arr(1,2,0) = 2.0F; + arr(1,2,1) = -3.0F; + arr(1,3,0) = 4.0F; + + checkRows ( arr, 4UL ); + checkColumns ( arr, 2UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 8UL ); + + if( blaze::isnan( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isnan evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +#if 0 +//************************************************************************************************* +/*!\brief Test of the \c isSquare() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isSquare() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsSquare() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isSquare()"; + + // Square array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns( arr, 3UL ); + + if( isSquare( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSquare evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns( arr, 3UL ); + + if( isSquare( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSquare evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } + + +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isSymmetric() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isSymmetric() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsSymmetric() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isSymmetric()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isSymmetric( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSymmetric evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isSymmetric( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSymmetric evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isSymmetric( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSymmetric evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-symmetric array (addition element in the lower part) + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,0) = 4; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isSymmetric( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSymmetric evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-symmetric array (addition element in the upper part) + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 4; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isSymmetric( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSymmetric evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Symmetric array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 4; + arr(1,1) = 2; + arr(2,0) = 4; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isSymmetric( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSymmetric evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isHermitian() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isHermitian() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsHermitian() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isHermitian()"; + + // Non-square array + { + blaze::DynamicArray<3, cplx> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isHermitian( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, cplx> arr( 3UL, 3UL, 0.0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isHermitian( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-real diagonal element + { + blaze::DynamicArray<3, cplx> arr( 3UL, 3UL, 0.0 ); + arr(1,1).imag( 1 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 1UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isHermitian( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-Hermitian array (additional element in the lower part) + { + blaze::DynamicArray<3, cplx> arr( 3UL, 3UL, 0.0 ); + arr(0,0).real( 1 ); + arr(1,1).real( 2 ); + arr(2,0).real( 4 ); + arr(2,2).real( 3 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isHermitian( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-Hermitian array (additional element in the upper part) + { + blaze::DynamicArray<3, cplx> arr( 3UL, 3UL, 0.0 ); + arr(0,0).real( 1 ); + arr(0,2).real( 4 ); + arr(1,1).real( 2 ); + arr(2,2).real( 3 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isHermitian( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-Hermitian array (invalid pair of elements) + { + blaze::DynamicArray<3, cplx> arr( 3UL, 3UL, 0.0 ); + arr(0,0).real( 1 ); + arr(0,2).imag( 4 ); + arr(1,1).real( 2 ); + arr(2,0).imag( 4 ); + arr(2,2).real( 3 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isHermitian( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Hermitian array + { + blaze::DynamicArray<3, cplx> arr( 3UL, 3UL, 0.0 ); + arr(0,0).real( 1 ); + arr(0,2).imag( 4 ); + arr(1,1).real( 2 ); + arr(2,0).imag( -4 ); + arr(2,2).real( 3 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isHermitian( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isHermitian evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* +#endif + +//************************************************************************************************* +/*!\brief Test of the \c isUniform() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isUniform() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsUniform() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isUniform()"; + + // Uniform array (0x0x3) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 0UL, 0UL, 3UL ); + + checkPages ( arr, 0UL ); + checkRows ( arr, 0UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 0UL ); + checkNonZeros( arr, 0UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Uniform array (0x3x0) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 0UL, 3UL, 0UL ); + + checkPages ( arr, 0UL ); + checkRows ( arr, 3UL ); + checkColumns ( arr, 0UL ); + checkCapacity( arr, 0UL ); + checkNonZeros( arr, 0UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Uniform array (2x0x0) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 2UL, 0UL, 0UL ); + + checkPages ( arr, 2UL ); + checkRows ( arr, 0UL ); + checkColumns ( arr, 0UL ); + checkCapacity( arr, 0UL ); + checkNonZeros( arr, 0UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Uniform array (2x1x3) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 2UL, 1UL, 3UL ); + + checkPages ( arr, 2UL ); + checkRows ( arr, 1UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 6UL ); + checkNonZeros( arr, 0UL, 0UL, 3UL ); + checkNonZeros( arr, 0UL, 1UL, 3UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Uniform array (2x3x1) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 2UL, 3UL, 1UL ); + + checkPages ( arr, 2UL ); + checkRows ( arr, 3UL ); + checkColumns ( arr, 1UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 6UL ); + checkNonZeros( arr, 0UL, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 0UL, 1UL ); + checkNonZeros( arr, 2UL, 0UL, 1UL ); + checkNonZeros( arr, 0UL, 1UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL, 1UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Uniform array (1x3x5) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 1UL, 3UL, 5UL ); + + checkPages ( arr, 1UL ); + checkRows ( arr, 3UL ); + checkColumns ( arr, 5UL ); + checkCapacity( arr, 15UL ); + checkNonZeros( arr, 15UL ); + checkNonZeros( arr, 0UL, 0UL, 5UL ); + checkNonZeros( arr, 1UL, 0UL, 5UL ); + checkNonZeros( arr, 2UL, 0UL, 5UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Uniform array (1x5x3) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 1UL, 5UL, 3UL ); + + checkPages ( arr, 1UL ); + checkRows ( arr, 5UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 15UL ); + checkNonZeros( arr, 15UL ); + checkNonZeros( arr, 0UL, 0UL, 3UL ); + checkNonZeros( arr, 1UL, 0UL, 3UL ); + checkNonZeros( arr, 2UL, 0UL, 3UL ); + checkNonZeros( arr, 3UL, 0UL, 3UL ); + checkNonZeros( arr, 4UL, 0UL, 3UL ); + + if( isUniform( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-uniform array (3x3x3) + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 5, 3UL, 3UL, 3UL ); + arr(2,2,2) = 3; + + checkPages ( arr, 3UL ); + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 27UL ); + checkNonZeros( arr, 27UL ); + checkNonZeros( arr, 0UL, 0UL, 3UL ); + checkNonZeros( arr, 1UL, 0UL, 3UL ); + checkNonZeros( arr, 2UL, 0UL, 3UL ); + checkNonZeros( arr, 0UL, 1UL, 3UL ); + checkNonZeros( arr, 1UL, 1UL, 3UL ); + checkNonZeros( arr, 2UL, 1UL, 3UL ); + checkNonZeros( arr, 0UL, 2UL, 3UL ); + checkNonZeros( arr, 1UL, 2UL, 3UL ); + checkNonZeros( arr, 2UL, 2UL, 3UL ); + + if( isUniform( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniform evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + +#if 0 +//************************************************************************************************* +/*!\brief Test of the \c isLower() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isLower() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsLower() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isLower()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-lower triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,0) = 3; + arr(1,1) = 4; + arr(2,2) = 5; + arr(2,0) = 6; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 6UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Lower triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,0) = 2; + arr(1,1) = 3; + arr(2,2) = 4; + arr(2,0) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isUniLower() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isUniLower() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsUniLower() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isUniLower()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isUniLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isUniLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Identity array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 1; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUniLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUniLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Lower unitriangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,0) = 2; + arr(1,1) = 1; + arr(2,2) = 1; + arr(2,0) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isUniLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Lower triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,0) = 2; + arr(1,1) = 3; + arr(2,2) = 4; + arr(2,0) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isUniLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-lower unitriangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,0) = 3; + arr(1,1) = 1; + arr(2,2) = 1; + arr(2,0) = 4; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 6UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isUniLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isStrictlyLower() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isStrictlyLower() function for dense arrays. In case +// an error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsStrictlyLower() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isStrictlyLower()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isStrictlyLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isStrictlyLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isStrictlyLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Strictly lower triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(1,0) = 2; + arr(2,0) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 2UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isStrictlyLower( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Lower triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,0) = 2; + arr(1,1) = 3; + arr(2,2) = 4; + arr(2,0) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isStrictlyLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-strictly lower triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,2) = 2; + arr(1,0) = 3; + arr(2,0) = 4; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isStrictlyLower( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyLower evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isUpper() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isUpper() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsUpper() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isUpper()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 3; + arr(1,2) = 4; + arr(2,0) = 5; + arr(2,2) = 6; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 6UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 3; + arr(1,2) = 4; + arr(2,2) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isUniUpper() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isUniUpper() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsUniUpper() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isUniUpper()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isUniUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isUniUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Identity array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 1; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUniUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUniUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Upper unitriangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 1; + arr(1,2) = 3; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUniUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 3; + arr(1,2) = 4; + arr(2,2) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isUniUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 1; + arr(1,2) = 3; + arr(2,0) = 4; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 6UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isUniUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isUniUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isStrictlyUpper() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isStrictlyUpper() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsStrictlyUpper() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isStrictlyUpper()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isStrictlyUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isStrictlyUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isStrictlyUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Strictly upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,2) = 2; + arr(1,2) = 4; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 2UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isStrictlyUpper( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 3; + arr(1,2) = 4; + arr(2,2) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 5UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 2UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isStrictlyUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Non-strictly upper triangular array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,2) = 2; + arr(1,2) = 3; + arr(2,0) = 4; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isStrictlyUpper( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isStrictlyUpper evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isDiagonal() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isDiagonal() function for dense arrays. In case +// an error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsDiagonal() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isDiagonal()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isDiagonal( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDiagonal evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isDiagonal( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDiagonal evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isDiagonal( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDiagonal evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Lower array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,0) = 4; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isDiagonal( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDiagonal evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Upper array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 4; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isDiagonal( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDiagonal evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isIdentity() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isIdentity() function for dense arrays. In case +// an error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testIsIdentity() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major isIdentity()"; + + // Non-square array + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL, 0 ); + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 6UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + + if( isIdentity( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Default initialized array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 0UL ); + checkNonZeros( arr, 0UL, 0UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 0UL ); + + if( isIdentity( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Identity array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 1; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isIdentity( arr ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Incomplete identity array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 0; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 2UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 0UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isIdentity( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Diagonal array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 2; + arr(2,2) = 3; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 3UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isIdentity( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Lower array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(1,1) = 1; + arr(2,0) = 2; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 1UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 2UL ); + + if( isIdentity( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Upper array + { + blaze::DynamicArray<3, int> arr( 3UL, 3UL, 0 ); + arr(0,0) = 1; + arr(0,2) = 2; + arr(1,1) = 1; + arr(2,2) = 1; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkCapacity( arr, 9UL ); + checkNonZeros( arr, 4UL ); + checkNonZeros( arr, 0UL, 2UL ); + checkNonZeros( arr, 1UL, 1UL ); + checkNonZeros( arr, 2UL, 1UL ); + + if( isIdentity( arr ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isIdentity evaluation\n" + << " Details:\n" + << " Array:\n" << arr << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + +#endif + +//************************************************************************************************* +/*!\brief Test of the \c min() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c min() function for dense arrays. In case an error +// is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testMinimum() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major min()"; + + // Attempt to find the minimum at the beginning in a fully filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 2UL ); + arr(0,0,0) = -1; + arr(0,0,1) = 2; + arr(0,1,0) = 3; + arr(0,1,1) = 4; + arr(0,2,0) = 5; + arr(0,2,1) = 6; + arr(1,0,0) = -1; + arr(1,0,1) = 2; + arr(1,1,0) = 3; + arr(1,1,1) = 4; + arr(1,2,0) = 5; + arr(1,2,1) = 6; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 2UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 12UL ); + + const int minimum = min( arr ); + + if( minimum != -1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: First computation failed\n" + << " Details:\n" + << " Result: " << minimum << "\n" + << " Expected result: -1\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to find the minimum at the end in a fully filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 2UL, 3UL ); + arr(0,0,0) = 1; + arr(0,0,1) = 2; + arr(0,0,2) = 3; + arr(0,1,0) = 4; + arr(0,1,1) = 5; + arr(0,1,2) = -6; + arr(1,0,0) = 1; + arr(1,0,1) = 2; + arr(1,0,2) = 3; + arr(1,1,0) = 4; + arr(1,1,1) = 5; + arr(1,1,2) = -6; + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 12UL ); + + const int minimum = min( arr ); + + if( minimum != -6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Second computation failed\n" + << " Details:\n" + << " Result: " << minimum << "\n" + << " Expected result: -6\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to find the minimum at the beginning in a partially filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 5UL, 3UL ); + arr(0,0,0) = -1; + arr(0,0,2) = 2; + arr(0,2,1) = 3; + arr(0,4,0) = 4; + arr(0,4,2) = 5; + arr(1,0,0) = -1; + arr(1,0,2) = 2; + arr(1,2,1) = 3; + arr(1,4,0) = 4; + arr(1,4,2) = 5; + + checkRows ( arr, 5UL ); + checkColumns ( arr, 3UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 10UL ); + + const int minimum = min( arr ); + + if( minimum != -1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Third computation failed\n" + << " Details:\n" + << " Result: " << minimum << "\n" + << " Expected result: -1\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to find the minimum at the end in a partially filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 5UL ); + arr(0,0,0) = 1; + arr(0,0,4) = 2; + arr(0,1,2) = 3; + arr(0,2,0) = 4; + arr(0,2,4) = -5; + arr(1,0,0) = 1; + arr(1,0,4) = 2; + arr(1,1,2) = 3; + arr(1,2,0) = 4; + arr(1,2,4) = -5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 5UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 10UL ); + + const int minimum = min( arr ); + + if( minimum != -5 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Fourth computation failed\n" + << " Details:\n" + << " Result: " << minimum << "\n" + << " Expected result: -5\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to detect 0 as the minimum value + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 3UL, 3UL, 3UL ); + arr(0,0,0) = 1; + arr(0,0,2) = 2; + arr(0,1,1) = 3; + arr(0,2,0) = 4; + arr(0,2,2) = 5; + arr(2,0,0) = 1; + arr(2,0,2) = 2; + arr(2,1,1) = 3; + arr(2,2,0) = 4; + arr(2,2,2) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkPages ( arr, 3UL ); + checkNonZeros( arr, 10UL ); + + const int minimum = min( arr ); + + if( minimum != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Fifth computation failed\n" + << " Details:\n" + << " Result: " << minimum << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c max() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c max() function for dense arrays. In case an error +// is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testMaximum() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major max()"; + + // Attempt to find the maximum at the beginning in a fully filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 2UL ); + arr(0,0,0) = 1; + arr(0,0,1) = -2; + arr(0,1,0) = -3; + arr(0,1,1) = -4; + arr(0,2,0) = -5; + arr(0,2,1) = -6; + arr(1,0,0) = 0; + arr(1,0,1) = -2; + arr(1,1,0) = -3; + arr(1,1,1) = -4; + arr(1,2,0) = -5; + arr(1,2,1) = -6; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 2UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 11UL ); + + const int maximum = max( arr ); + + if( maximum != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: First computation failed\n" + << " Details:\n" + << " Result: " << maximum << "\n" + << " Expected result: 1\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to find the maximum at the end in a fully filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 2UL, 3UL ); + arr(0,0,0) = -1; + arr(0,0,1) = -2; + arr(0,0,2) = -3; + arr(0,1,0) = -4; + arr(0,1,1) = -5; + arr(0,1,2) = -6; + arr(1,0,0) = -1; + arr(1,0,1) = -2; + arr(1,0,2) = -3; + arr(1,1,0) = -4; + arr(1,1,1) = -5; + arr(1,1,2) = 6; + + checkRows ( arr, 2UL ); + checkColumns ( arr, 3UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 12UL ); + + const int maximum = max( arr ); + + if( maximum != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Second computation failed\n" + << " Details:\n" + << " Result: " << maximum << "\n" + << " Expected result: 6\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to find the maximum at the beginning in a partially filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 5UL, 3UL ); + arr(0,0,0) = 1; + arr(0,0,2) = -2; + arr(0,2,1) = -3; + arr(0,4,0) = -4; + arr(0,4,2) = -5; + arr(1,0,0) = 0; + arr(1,0,2) = -2; + arr(1,2,1) = -3; + arr(1,4,0) = -4; + arr(1,4,2) = -5; + + checkRows ( arr, 5UL ); + checkColumns ( arr, 3UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 9UL ); + + const int maximum = max( arr ); + + if( maximum != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Third computation failed\n" + << " Details:\n" + << " Result: " << maximum << "\n" + << " Expected result: 1\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to find the maximum at the end in a partially filled array + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 5UL ); + arr(0,0,0) = -1; + arr(0,0,4) = -2; + arr(0,1,2) = -3; + arr(0,2,0) = -4; + arr(0,2,4) = -5; + arr(1,0,0) = -1; + arr(1,0,4) = -2; + arr(1,1,2) = -3; + arr(1,2,0) = -4; + arr(1,2,4) = 5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 5UL ); + checkPages ( arr, 2UL ); + checkNonZeros( arr, 10UL ); + + const int maximum = max( arr ); + + if( maximum != 5 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Fourth computation failed\n" + << " Details:\n" + << " Result: " << maximum << "\n" + << " Expected result: 5\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Attempt to detect 0 as the maximum value + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 3UL, 3UL, 3UL ); + arr(0,0,0) = -1; + arr(0,0,2) = -2; + arr(0,1,1) = -3; + arr(0,2,0) = -4; + arr(0,2,2) = -5; + arr(2,0,0) = -1; + arr(2,0,2) = -2; + arr(2,1,1) = -3; + arr(2,2,0) = -4; + arr(2,2,2) = -5; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkPages ( arr, 3UL ); + checkNonZeros( arr, 10UL ); + + const int maximum = max( arr ); + + if( maximum != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Fifth computation failed\n" + << " Details:\n" + << " Result: " << maximum << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c softmax() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c softmax() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testSoftmax() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major softmax()"; + + blaze::DynamicArray<3, double> A( 2UL, 2UL, 2UL ); + randomize( A, -5.0, 5.0 ); + + const auto B = softmax( A ); + + if( B(0,0,0) <= 0.0 || B(0,0,0) > 1.0 || + B(0,0,1) <= 0.0 || B(0,0,1) > 1.0 || + B(0,1,0) <= 0.0 || B(0,1,0) > 1.0 || + B(0,1,1) <= 0.0 || B(0,1,1) > 1.0 || + B(1,0,0) <= 0.0 || B(1,0,0) > 1.0 || + B(1,0,1) <= 0.0 || B(1,0,1) > 1.0 || + B(1,1,0) <= 0.0 || B(1,1,0) > 1.0 || + B(1,1,1) <= 0.0 || B(1,1,1) > 1.0 || + !isEqual( sum( B ), 1.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Softmax computation failed\n" + << " Details:\n" + << " Result: " << sum( B ) << "\n" + << " Expected result: 1\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +#if 0 +//************************************************************************************************* +/*!\brief Test of the \c trace() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c trace() function for dense arrays. In case an error +// is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testTrace() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "Row-major trace()"; + + // Determining the trace of a 0x0 array + { + blaze::DynamicArray<3, int> arr; + + checkRows ( arr, 0UL ); + checkColumns( arr, 0UL ); + + const int trace = blaze::trace( arr ); + + if( trace != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: First computation failed\n" + << " Details:\n" + << " Result: " << trace << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Determining the trace of a 3x3 array + { + const blaze::DynamicArray<3, int> arr{ { -1, 2, -3 } + , { -4, -5, 6 } + , { 7, -8, -9 } }; + + checkRows ( arr, 3UL ); + checkColumns ( arr, 3UL ); + checkNonZeros( arr, 9UL ); + + const int trace = blaze::trace( arr ); + + if( trace != -15 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Second computation failed\n" + << " Details:\n" + << " Result: " << trace << "\n" + << " Expected result: -15\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Determining the trace of a non-square array + try + { + blaze::DynamicArray<3, int> arr( 2UL, 3UL ); + + checkRows ( arr, 2UL ); + checkColumns( arr, 3UL ); + + const int trace = blaze::trace( arr ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Trace computation on a non-square array succeeded\n" + << " Details:\n" + << " Result:\n" << trace << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* +#endif + +//************************************************************************************************* +/*!\brief Test of the \c l1Norm() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c l1Norm() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testL1Norm() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "l1Norm() function"; + + { + blaze::DynamicArray<3, int> arr; + + const int norm = blaze::l1Norm( arr ); + + if( !isEqual( norm, 0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L1 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 7UL ); + + const int norm = blaze::l1Norm( arr ); + + if( !isEqual( norm, 0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L1 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray< 3, int > arr{ + {{{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}, + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}}}; + + const int norm = blaze::l1Norm( arr ); + + if( !isEqual( norm, 14 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L1 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 14\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief Test of the \c l2Norm() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c l2Norm() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testL2Norm() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "l2Norm() function"; + + { + blaze::DynamicArray<3, int> arr; + + const double norm = blaze::l2Norm( arr ); + + if( !isEqual( norm, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L2 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 7UL ); + + const double norm = blaze::l2Norm( arr ); + + if( !isEqual( norm, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L2 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray< 3, int > arr{{ + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}, + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}}}; + + const double norm = blaze::l2Norm( arr ); + + if( !isEqual( norm, 4.6904157598234297 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L2 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 4.6904157598234297\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c l3Norm() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c l3Norm() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testL3Norm() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "l3Norm() function"; + + { + blaze::DynamicArray<3, int> arr; + + const double norm = blaze::l3Norm( arr ); + + if( !isEqual( norm, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L3 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 7UL ); + + const double norm = blaze::l3Norm( arr ); + + if( !isEqual( norm, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L3 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int > arr{{ + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}, + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}}}; + + const double norm = blaze::l3Norm( arr ); + + if( !isEqual( norm, 3.3619754067989636 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L3 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 3.3619754067989636\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c l4Norm() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c l4Norm() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testL4Norm() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "l4Norm() function"; + + { + blaze::DynamicArray<3, int> arr; + + const double norm = blaze::l4Norm( arr ); + + if( !isEqual( norm, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L4 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 7UL ); + + const double norm = blaze::l4Norm( arr ); + + if( !isEqual( norm, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L4 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int > arr{{ + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}, + {{0, 0, 1, 0, 1, 0, 0}, {0, -2, 0, 0, 0, -1, 0}, + {0, 0, 0, 2, 0, 0, 0}}}}; + + const double norm = blaze::l4Norm( arr ); + + if( !isEqual( norm, 2.8925076085190780 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: L4 norm computation failed\n" + << " Details:\n" + << " Result: " << norm << "\n" + << " Expected result: 2.8925076085190780\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c lpNorm() function for dense arrays. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c lpNorm() function for dense arrays. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void GeneralTest::testLpNorm() +{ + //===================================================================================== + // Row-major array tests + //===================================================================================== + + { + test_ = "lpNorm() function"; + + { + blaze::DynamicArray<3, int> arr; + + const double norm1 = blaze::lpNorm( arr, 2 ); + const double norm2 = blaze::lpNorm<2UL>( arr ); + + if( !isEqual( norm1, 0.0 ) || !isEqual( norm2, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Lp norm computation failed\n" + << " Details:\n" + << " lpNorm<2>(): " << norm1 << "\n" + << " lpNorm(2): " << norm2 << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( blaze::init_from_value, 0, 2UL, 3UL, 7UL ); + + const double norm1 = blaze::lpNorm( arr, 2 ); + const double norm2 = blaze::lpNorm<2UL>( arr ); + + if( !isEqual( norm1, 0.0 ) || !isEqual( norm2, 0.0 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Lp norm computation failed\n" + << " Details:\n" + << " lpNorm<2>(): " << norm1 << "\n" + << " lpNorm(2): " << norm2 << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( 2UL, 5UL, 10UL ); + randomize( arr, -5, 5 ); + + const int norm1( blaze::lpNorm( arr, 1 ) ); + const int norm2( blaze::lpNorm<1UL>( arr ) ); + const int norm3( blaze::l1Norm( arr ) ); + + if( !isEqual( norm1, norm3 ) || !isEqual( norm2, norm3 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Lp norm computation failed\n" + << " Details:\n" + << " lpNorm<1>(): " << norm1 << "\n" + << " lpNorm(1): " << norm2 << "\n" + << " Expected result: " << norm3 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( 2UL, 5UL, 10UL ); + randomize( arr, -5, 5 ); + + const double norm1( blaze::lpNorm( arr, 2 ) ); + const double norm2( blaze::lpNorm<2UL>( arr ) ); + const double norm3( blaze::l2Norm( arr ) ); + + if( !isEqual( norm1, norm3 ) || !isEqual( norm2, norm3 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Lp norm computation failed\n" + << " Details:\n" + << " lpNorm<2>(): " << norm1 << "\n" + << " lpNorm(2): " << norm2 << "\n" + << " Expected result: " << norm3 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( 2UL, 5UL, 10UL ); + randomize( arr, -5, 5 ); + + const double norm1( blaze::lpNorm( arr, 3 ) ); + const double norm2( blaze::lpNorm<3UL>( arr ) ); + const double norm3( blaze::l3Norm( arr ) ); + + if( !isEqual( norm1, norm3 ) || !isEqual( norm2, norm3 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Lp norm computation failed\n" + << " Details:\n" + << " lpNorm<3>(): " << norm1 << "\n" + << " lpNorm(3): " << norm2 << "\n" + << " Expected result: " << norm3 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + blaze::DynamicArray<3, int> arr( 2UL, 5UL, 10UL ); + randomize( arr, -5, 5 ); + + const double norm1( blaze::lpNorm( arr, 4 ) ); + const double norm2( blaze::lpNorm<4UL>( arr ) ); + const double norm3( blaze::l4Norm( arr ) ); + + if( !isEqual( norm1, norm3 ) || !isEqual( norm2, norm3 ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Lp norm computation failed\n" + << " Details:\n" + << " lpNorm<4>(): " << norm1 << "\n" + << " lpNorm(4): " << norm2 << "\n" + << " Expected result: " << norm3 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + +} // namespace densearray + +} // namespace mathtest + +} // namespace blazetest + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + std::cout << " Running general DenseArray operation test..." << std::endl; + + try + { + RUN_DENSEARRAY_GENERAL_TEST; + } + catch( std::exception& ex ) { + std::cerr << "\n\n ERROR DETECTED during general DenseArray operation test:\n" + << ex.what() << "\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +//************************************************************************************************* From 2703810e3e19cdf4181e9f86768808ada9b9558e Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Wed, 29 May 2019 07:45:59 -0500 Subject: [PATCH 02/14] Fix nested comment warning --- blaze_tensor/math/views/DilatedSubmatrix.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/blaze_tensor/math/views/DilatedSubmatrix.h b/blaze_tensor/math/views/DilatedSubmatrix.h index 9b6fccb..d77fab2 100644 --- a/blaze_tensor/math/views/DilatedSubmatrix.h +++ b/blaze_tensor/math/views/DilatedSubmatrix.h @@ -332,11 +332,11 @@ inline decltype(auto) dilatedsubmatrix( Matrix&& matrix, RSAs... args ) // Please note that this function creates an unaligned dense or sparse DilatedSubmatrix. For instance, // the creation of the dense DilatedSubmatrix is equivalent to the following function call: - -************************************************************************************************* +*/ +//************************************************************************************************* -************************************************************************************************* +//************************************************************************************************* /*!\brief Creating a view on a specific DilatedSubmatrix of the given matrix. // \ingroup DilatedSubmatrix // From a120a0ff69e46c2aa782a07e097ff095e324be52 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Wed, 29 May 2019 12:44:17 -0500 Subject: [PATCH 03/14] Fixing more compilation problems --- blaze_tensor/math/dense/DenseArray.h | 2 +- blaze_tensor/math/dense/DynamicArray.h | 29 ++++++++++++------- blaze_tensor/math/expressions/Array.h | 2 +- .../math/expressions/DArrDArrMapExpr.h | 4 +-- .../math/expressions/DArrReduceExpr.h | 8 ++--- blaze_tensor/math/smp/ArrayThreadMapping.h | 4 +-- blaze_tensor/util/ArrayForEach.h | 2 +- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/blaze_tensor/math/dense/DenseArray.h b/blaze_tensor/math/dense/DenseArray.h index cb34e11..1fe3e24 100644 --- a/blaze_tensor/math/dense/DenseArray.h +++ b/blaze_tensor/math/dense/DenseArray.h @@ -137,7 +137,7 @@ inline auto operator==( const DenseArray& arr, T2 scalar ) using CT1 = CompositeType_t; constexpr size_t N = - RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); + RemoveCV_t< RemoveReference_t< decltype( ~arr ) > >::num_dimensions(); // Evaluation of the dense array operand CT1 A( ~arr ); diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index 03a7590..6ef51ca 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -549,7 +549,7 @@ inline DynamicArray::DynamicArray( InitFromValue, const Type& init, Dim \code using blaze::rowMajor; - blaze::DynamicArray A{ { { 1, 2, 3 }, + blaze::DynamicArray<3, int> A{ { { 1, 2, 3 }, { 4, 5 }, { 7, 8, 9 } }, { { 1, 2, 3 }, @@ -588,7 +588,7 @@ inline DynamicArray::DynamicArray( nested_initializer_list< N, Type > l int* array = new int[20]; // ... Initialization of the dynamic array - blaze::DynamicArray v( 6UL, 4UL, 5UL, array ); + blaze::DynamicArray<3, int> v( array, 6UL, 4UL, 5UL ); delete[] array; \endcode @@ -604,7 +604,16 @@ inline DynamicArray::DynamicArray( const Other* array, Dims... dims ) { BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); - ArrayForEach2( dims_, nn_, [&]( size_t i, size_t j ) { v_[i] = array[j]; } ); + if( IsNothrowMoveAssignable_v< ValueType > ) { + ArrayForEach2( dims_, nn_, [&]( size_t i, size_t j ) { + v_[j] = std::move( array[i] ); + } ); + } + else { + ArrayForEach2( dims_, nn_, [&]( size_t i, size_t j ) { + v_[j] = array[i]; + } ); + } BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); } @@ -1169,7 +1178,7 @@ inline typename DynamicArray::ConstIterator { BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); - return ConstIterator( v_ + row_index( size_t i, dims... ) + dims_[0] ); + return ConstIterator( v_ + row_index( i, dims... ) + dims_[0] ); } //************************************************************************************************* @@ -1235,7 +1244,7 @@ inline DynamicArray& DynamicArray::operator=(const Type& rhs) \code using blaze::rowMajor; - blaze::DynamicArray A; + blaze::DynamicArray<3, int> A; A = { { { 1, 2, 3 }, { 4, 5 }, { 7, 8, 9 } } }; @@ -1581,7 +1590,7 @@ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array inline void DynamicArray::reset() { - ArrayForEach( dims_, []( size_t i ) { blaze::clear( v_[i] ); } ); + ArrayForEach( dims_, [&]( size_t i ) { blaze::clear( v_[i] ); } ); } //************************************************************************************************* @@ -1684,7 +1693,7 @@ void DynamicArray::resize( std::array< size_t, N > const& dims, bool pr const size_t nn( addPadding( dims[0] ) ); size_t new_capacity = nn; - for( size_t i = 1; i < n; ++i ) { + for( size_t i = 1; i < N; ++i ) { new_capacity *= dims[i]; } @@ -2176,7 +2185,7 @@ inline DynamicArray& DynamicArray::ctranspose( const T* indice // multiplication assignment operator: \code - blaze::DynamicArray A; + blaze::DynamicArray<3, int> A; // ... Resizing and initialization A *= 4; // Scaling of the array A.scale( 4 ); // Same effect as above @@ -3037,7 +3046,7 @@ inline void clear( DynamicArray& m ) // \a isDefault() function: \code - blaze::DynamicArray A; + blaze::DynamicArray<3, int> A; // ... Resizing and initialization if( isDefault( A ) ) { ... } \endcode @@ -3073,7 +3082,7 @@ inline bool isDefault( const DynamicArray& m ) // function: \code - blaze::DynamicArray A; + blaze::DynamicArray<3, int> A; // ... Resizing and initialization if( isIntact( A ) ) { ... } \endcode diff --git a/blaze_tensor/math/expressions/Array.h b/blaze_tensor/math/expressions/Array.h index 8d2c46a..3b386e0 100644 --- a/blaze_tensor/math/expressions/Array.h +++ b/blaze_tensor/math/expressions/Array.h @@ -368,7 +368,7 @@ BLAZE_ALWAYS_INLINE bool tryDiv( const Array& arr, std::array< size_t, N > c } ); #endif - MAYBE_UNUSED( mat, dims, value ); + MAYBE_UNUSED( arr, dims, value ); return true; } diff --git a/blaze_tensor/math/expressions/DArrDArrMapExpr.h b/blaze_tensor/math/expressions/DArrDArrMapExpr.h index c747ca4..9adc98d 100644 --- a/blaze_tensor/math/expressions/DArrDArrMapExpr.h +++ b/blaze_tensor/math/expressions/DArrDArrMapExpr.h @@ -462,8 +462,8 @@ class DArrDArrMapExpr inline ReturnType at( Dims... dims ) const { constexpr size_t indices[] = {dims...}; - ArrayDimForEach( dims_, [&]( size_t i ) { - if( indices[i] >= dims_[i + 1] ) { + ArrayDimForEach( lhs_.dimensions(), [&]( size_t i ) { + if( indices[i] >= lhs_.dimensions()[i] ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); diff --git a/blaze_tensor/math/expressions/DArrReduceExpr.h b/blaze_tensor/math/expressions/DArrReduceExpr.h index 331ebe7..0956c63 100644 --- a/blaze_tensor/math/expressions/DArrReduceExpr.h +++ b/blaze_tensor/math/expressions/DArrReduceExpr.h @@ -455,8 +455,8 @@ class ReducedArray inline ReturnType at( Dims... dims ) const { constexpr size_t indices[] = {dims...}; - ArrayDimForEach( dims_, [&]( size_t i ) { - if( indices[i] >= dims_[i + 1] ) { + ArrayDimForEach( dm_.dimensions(), [&]( size_t i ) { + if( indices[i] >= dm_.dimensions()[i] ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); @@ -575,7 +575,7 @@ class ReducedArray // \return \a true in case the expression can be used in SMP assignments, \a false if not. */ inline bool canSMPAssign() const noexcept { - return dm_.canSMPAssign() || ( rows() * columns() > SMP_DMATREDUCE_THRESHOLD ); + return dm_.canSMPAssign() || ( dimensions<1>() * dimensions<0>() > SMP_DMATREDUCE_THRESHOLD ); } //********************************************************************************************** @@ -958,7 +958,7 @@ inline ElementType_t darrayreduce( const DenseArray& dm, OP op ) ET redux{}; - ArrayForEachGrouped( ( ~dm ).dimensions(), + ArrayForEachGrouped( ( ~dm ).dimensions(), [&]( std::array< size_t, N > const& dims ) { redux = op( redux, tmp( dims ) ); } ); diff --git a/blaze_tensor/math/smp/ArrayThreadMapping.h b/blaze_tensor/math/smp/ArrayThreadMapping.h index 42c94a1..ffd2ec2 100644 --- a/blaze_tensor/math/smp/ArrayThreadMapping.h +++ b/blaze_tensor/math/smp/ArrayThreadMapping.h @@ -75,8 +75,8 @@ namespace blaze { template< typename MT >// Type of the tensor ThreadMapping createThreadMapping( size_t threads, const Array& A ) { - const size_t M( (~A).dimension<1>() ); - const size_t N( (~A).dimension<0>() ); + const size_t M( (~A).template dimension<1>() ); + const size_t N( (~A).template dimension<0>() ); if( M > N ) { diff --git a/blaze_tensor/util/ArrayForEach.h b/blaze_tensor/util/ArrayForEach.h index f420098..788ada4 100644 --- a/blaze_tensor/util/ArrayForEach.h +++ b/blaze_tensor/util/ArrayForEach.h @@ -276,7 +276,7 @@ template< typename F > void ArrayForEach2( size_t dim0, F const& f, size_t base1, size_t base2 ) { - for( size_t i = 0; i != dims[0]; ++i ) { + for( size_t i = 0; i != dim0; ++i ) { f( i + base1, i + base2 ); } } From 21ac381605f5f0f539befbdee2ea9800e8c7fe3e Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 30 May 2019 12:43:52 -0500 Subject: [PATCH 04/14] Adding arrayslice and friends --- blaze_tensor/math/ArraySlice.h | 157 + blaze_tensor/math/IntegerSequence.h | 52 + blaze_tensor/math/constraints/ArraySlice.h | 88 + blaze_tensor/math/dense/DynamicArray.h | 31 +- blaze_tensor/math/expressions/Array.h | 93 +- blaze_tensor/math/expressions/Forward.h | 9 +- blaze_tensor/math/traits/ArraySliceTrait.h | 211 + blaze_tensor/math/typetraits/IsArraySlice.h | 168 + blaze_tensor/math/views/ArraySlice.h | 1634 ++++++ blaze_tensor/math/views/Forward.h | 55 + .../math/views/arrayslice/ArraySlice.h | 328 ++ .../math/views/arrayslice/ArraySliceData.h | 251 + .../math/views/arrayslice/BaseTemplate.h | 123 + blaze_tensor/math/views/arrayslice/Dense.h | 2129 +++++++ blaze_tensor/util/ArrayForEach.h | 41 +- .../mathtest/arrayslice/DenseGeneralTest.h | 432 ++ blazetest/src/mathtest/CMakeLists.txt | 1 + .../src/mathtest/arrayslice/CMakeLists.txt | 44 + .../mathtest/arrayslice/DenseGeneralTest.cpp | 5157 +++++++++++++++++ .../src/mathtest/arrayslice/IncludeTest.cpp | 61 + 20 files changed, 11012 insertions(+), 53 deletions(-) create mode 100644 blaze_tensor/math/ArraySlice.h create mode 100644 blaze_tensor/math/constraints/ArraySlice.h create mode 100644 blaze_tensor/math/traits/ArraySliceTrait.h create mode 100644 blaze_tensor/math/typetraits/IsArraySlice.h create mode 100644 blaze_tensor/math/views/ArraySlice.h create mode 100644 blaze_tensor/math/views/arrayslice/ArraySlice.h create mode 100644 blaze_tensor/math/views/arrayslice/ArraySliceData.h create mode 100644 blaze_tensor/math/views/arrayslice/BaseTemplate.h create mode 100644 blaze_tensor/math/views/arrayslice/Dense.h create mode 100644 blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h create mode 100644 blazetest/src/mathtest/arrayslice/CMakeLists.txt create mode 100644 blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp create mode 100644 blazetest/src/mathtest/arrayslice/IncludeTest.cpp diff --git a/blaze_tensor/math/ArraySlice.h b/blaze_tensor/math/ArraySlice.h new file mode 100644 index 0000000..a761645 --- /dev/null +++ b/blaze_tensor/math/ArraySlice.h @@ -0,0 +1,157 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/ArraySlice.h +// \brief Header file for the complete ArraySlice implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_ARRAYSLICE_H_ +#define _BLAZE_TENSOR_MATH_ARRAYSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// RAND SPECIALIZATION FOR DENSE ARRAYSLICES +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the Rand class template for dense arrayslices. +// \ingroup random +// +// This specialization of the Rand class randomizes dense arrayslices. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +class Rand< ArraySlice > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + template< typename RT > + inline void randomize( RT&& arrayslice ) const; + + template< typename RT, typename Arg > + inline void randomize( RT&& arrayslice, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a dense arrayslice. +// +// \param arrayslice The arrayslice to be randomized. +// \return void +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename RT > // Type of the arrayslice +inline void Rand< ArraySlice >::randomize( RT&& arrayslice ) const +{ + using blaze::randomize; + + using ArraySliceType = RemoveReference_t; + + BLAZE_CONSTRAINT_MUST_BE_ARRAYSLICE_TYPE ( ArraySliceType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ArraySliceType ); + + constexpr size_t N = ArraySliceType::num_dimensions(); + + ArrayForEachGrouped( + arrayslice.dimensions(), [&]( std::array< size_t, N > const& indices ) { + randomize( arrayslice( indices ) ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a dense arrayslice. +// +// \param arrayslice The arrayslice to be randomized. +// \param min The smallest possible value for a arrayslice element. +// \param max The largest possible value for a arrayslice element. +// \return void +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename RT // Type of the arrayslice + , typename Arg > // Min/max argument type +inline void Rand< ArraySlice >::randomize( RT&& arrayslice, const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + using ArraySliceType = RemoveReference_t; + + BLAZE_CONSTRAINT_MUST_BE_ARRAYSLICE_TYPE ( ArraySliceType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ArraySliceType ); + + constexpr size_t N = ArraySliceType::num_dimensions(); + + ArrayForEachGrouped( + arrayslice.dimensions(), [&]( std::array< size_t, N > const& indices ) { + randomize( arrayslice( indices ), min, max ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/IntegerSequence.h b/blaze_tensor/math/IntegerSequence.h index 396fb56..f3e9e68 100644 --- a/blaze_tensor/math/IntegerSequence.h +++ b/blaze_tensor/math/IntegerSequence.h @@ -41,8 +41,10 @@ // Includes //************************************************************************************************* +#include #include #include +#include namespace blaze { @@ -120,6 +122,56 @@ using make_dilated_index_subsequence = decltype( subsequence( dilate( shift( make_index_sequence() ) ) ) ); //************************************************************************************************* + +//************************************************************************************************* +/*!\brief Auxiliary function object allowing to split index sequences into two. +// \ingroup math +*/ +template< size_t... Is1, size_t... Is2, typename... Ts, typename... Dims > +BLAZE_ALWAYS_INLINE decltype( auto ) fused_indices( index_sequence< Is1... >, + size_t index, index_sequence< Is2... >, std::tuple< Ts... > indices, Dims... dims ) +{ + constexpr size_t N = sizeof...(Is1) + sizeof...(Is2) + sizeof...(Dims) + 1; + return std::array< size_t, N >{ + size_t( std::get< Is1 >( indices ) )..., + index, + size_t( std::get< Is2 >( indices ) )..., + size_t( dims )...}; +} + +template< size_t M, typename... Dims > +BLAZE_ALWAYS_INLINE decltype(auto) fused_indices( size_t index, Dims... dims ) +{ + BLAZE_STATIC_ASSERT( M < sizeof...( Dims ) ); + + return fused_indices( make_index_sequence< M >{}, index, + make_shifted_index_sequence< M, sizeof...( Dims ) >{}, + std::forward_as_tuple( dims... ) ); +} + +template< size_t N, size_t... Is > +BLAZE_ALWAYS_INLINE decltype(auto) array_to_tuple( std::array< size_t, N > const& indices, index_sequence< Is... > ) +{ + return std::forward_as_tuple( indices[Is]... ); +} + +template< size_t N > +BLAZE_ALWAYS_INLINE decltype(auto) array_to_tuple(std::array< size_t, N > const& indices) +{ + return array_to_tuple( indices, make_index_sequence< N >{} ); +} + +template< size_t M, size_t N, typename... Dims > +BLAZE_ALWAYS_INLINE decltype(auto) fused_indices( size_t index, std::array< size_t, N > const& indices, Dims... dims ) +{ + BLAZE_STATIC_ASSERT( M < N ); + + return fused_indices( + make_index_sequence< M >{}, index, make_shifted_index_sequence< M, N >{}, + array_to_tuple( indices ), dims... ); +} +//************************************************************************************************* + } // namespace blaze #endif diff --git a/blaze_tensor/math/constraints/ArraySlice.h b/blaze_tensor/math/constraints/ArraySlice.h new file mode 100644 index 0000000..dfe24ec --- /dev/null +++ b/blaze_tensor/math/constraints/ArraySlice.h @@ -0,0 +1,88 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/constraints/ArraySlice.h +// \brief Constraint on the data type +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_CONSTRAINTS_ARRAYSLICE_H_ +#define _BLAZE_TENSOR_MATH_CONSTRAINTS_ARRAYSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// MUST_BE_PAGESLICE_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is not a arrayslice type (i.e. a dense or sparse arrayslice), a compilation +// error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_ARRAYSLICE_TYPE(T) \ + static_assert( ::blaze::IsArraySlice_v, "Non-arrayslice type detected" ) +//************************************************************************************************* + + + + +//================================================================================================= +// +// MUST_NOT_BE_PAGESLICE_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is a arrayslice type (i.e. a dense or sparse arrayslice), a compilation +// error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_ARRAYSLICE_TYPE(T) \ + static_assert( !::blaze::IsArraySlice_v, "ArraySlice type detected" ) +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index 6ef51ca..e650b9c 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -45,27 +45,31 @@ #include #include +#include #include +#include +#include +#include #include #include #include #include #include -#include #include #include #include +#include #include -#include #include +#include #include -#include #include #include +#include +#include #include #include -#include #include namespace blaze { @@ -3429,6 +3433,25 @@ struct DivTraitEval2< DynamicArray, T2 +//================================================================================================= +// +// ARRAYSLICETRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, size_t N, typename ET, size_t I > +struct ArraySliceTraitEval2< M, DynamicArray, I > +{ + using Type = DynamicArray< N - 1, ET >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + //================================================================================================= // // MAPTRAIT SPECIALIZATIONS diff --git a/blaze_tensor/math/expressions/Array.h b/blaze_tensor/math/expressions/Array.h index 3b386e0..a339482 100644 --- a/blaze_tensor/math/expressions/Array.h +++ b/blaze_tensor/math/expressions/Array.h @@ -185,14 +185,18 @@ inline TT1& operator*=( Array&& lhs, const Array& rhs ) // assignment operator. */ template< typename MT // Type of the array + , size_t N // Number of dimensions , typename ET > // Type of the element -BLAZE_ALWAYS_INLINE bool trySet( const Array& mat, size_t k, size_t i, size_t j, const ET& value ) +BLAZE_ALWAYS_INLINE bool trySet( const Array& arr, std::array< size_t, N > const& dims, const ET& value ) { - BLAZE_INTERNAL_ASSERT( i < (~mat).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < (~mat).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( k < (~mat).pages(), "Invalid page access index" ); +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& arrdims = ( ~arr ).dimensions(); + ArrayDimForEach( arrdims, [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + } ); +#endif - MAYBE_UNUSED( mat, k, i, j, value ); + MAYBE_UNUSED( arr, dims, value ); return true; } @@ -218,14 +222,18 @@ BLAZE_ALWAYS_INLINE bool trySet( const Array& mat, size_t k, size_t i, size_ // assignment operator. */ template< typename MT // Type of the array + , size_t N // Number of dimensions , typename ET > // Type of the element -BLAZE_ALWAYS_INLINE bool tryAdd( const Array& mat, size_t k, size_t i, size_t j, const ET& value ) +BLAZE_ALWAYS_INLINE bool tryAdd( const Array& arr, std::array< size_t, N > const& dims, const ET& value ) { - BLAZE_INTERNAL_ASSERT( i < (~mat).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < (~mat).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( k < (~mat).pages(), "Invalid page access index" ); +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& arrdims = ( ~arr ).dimensions(); + ArrayDimForEach( arrdims, [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + } ); +#endif - MAYBE_UNUSED( mat, k, i, j, value ); + MAYBE_UNUSED( arr, dims, value ); return true; } @@ -251,14 +259,18 @@ BLAZE_ALWAYS_INLINE bool tryAdd( const Array& mat, size_t k, size_t i, size_ // assignment operator. */ template< typename MT // Type of the array + , size_t N // Number of dimensions , typename ET > // Type of the element -BLAZE_ALWAYS_INLINE bool trySub( const Array& mat, size_t k, size_t i, size_t j, const ET& value ) +BLAZE_ALWAYS_INLINE bool trySub( const Array& arr, std::array< size_t, N > const& dims, const ET& value ) { - BLAZE_INTERNAL_ASSERT( i < (~mat).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < (~mat).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( k < (~mat).pages(), "Invalid page access index" ); +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& arrdims = ( ~arr ).dimensions(); + ArrayDimForEach( arrdims, [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + } ); +#endif - MAYBE_UNUSED( mat, k, i, j, value ); + MAYBE_UNUSED( arr, dims, value ); return true; } @@ -284,14 +296,18 @@ BLAZE_ALWAYS_INLINE bool trySub( const Array& mat, size_t k, size_t i, size_ // assignment operator. */ template< typename MT // Type of the array + , size_t N // Number of dimensions , typename ET > // Type of the element -BLAZE_ALWAYS_INLINE bool tryMult( const Array& tens, size_t k, size_t i, size_t j, const ET& value ) +BLAZE_ALWAYS_INLINE bool tryMult( const Array& arr, std::array< size_t, N > const& dims, const ET& value ) { - BLAZE_INTERNAL_ASSERT( i < (~tens).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < (~tens).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( k < (~tens).pages(), "Invalid page access index" ); +#if defined(BLAZE_INTERNAL_ASSERTION) + auto const& arrdims = ( ~arr ).dimensions(); + ArrayDimForEach( arrdims, [&]( size_t i ) { + BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + } ); +#endif - MAYBE_UNUSED( tens, k, i, j, value ); + MAYBE_UNUSED( arr, dims, value ); return true; } @@ -320,18 +336,19 @@ BLAZE_ALWAYS_INLINE bool tryMult( const Array& tens, size_t k, size_t i, siz // assignment operator. */ template< typename MT // Type of the array + , size_t N // Number of dimensions , typename ET > // Type of the element BLAZE_ALWAYS_INLINE bool - tryMult( const Array& tens, size_t row, size_t column, size_t page, size_t o, size_t m, size_t n, const ET& value ) + tryMult( const Array& arr, std::array< size_t, N > const& sizes, std::array< size_t, N > const& indices, const ET& value ) { - BLAZE_INTERNAL_ASSERT( row <= (~tens).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( column <= (~tens).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( page <= (~tens).pages(), "Invalid page access index" ); - BLAZE_INTERNAL_ASSERT( row + m <= (~tens).rows(), "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( column + n <= (~tens).columns(), "Invalid number of columns" ); - BLAZE_INTERNAL_ASSERT( page + o <= (~tens).pages(), "Invalid number of pages" ); - - MAYBE_UNUSED( tens, page, row, column, o, m, n, value ); +// BLAZE_INTERNAL_ASSERT( row <= (~tens).rows(), "Invalid row access index" ); +// BLAZE_INTERNAL_ASSERT( column <= (~tens).columns(), "Invalid column access index" ); +// BLAZE_INTERNAL_ASSERT( page <= (~tens).pages(), "Invalid page access index" ); +// BLAZE_INTERNAL_ASSERT( row + m <= (~tens).rows(), "Invalid number of rows" ); +// BLAZE_INTERNAL_ASSERT( column + n <= (~tens).columns(), "Invalid number of columns" ); +// BLAZE_INTERNAL_ASSERT( page + o <= (~tens).pages(), "Invalid number of pages" ); +// +// MAYBE_UNUSED( tens, page, row, column, o, m, n, value ); return true; } @@ -357,14 +374,14 @@ BLAZE_ALWAYS_INLINE bool // assignment operator. */ template< typename MT // Type of the array - , size_t N // number of dimensions + , size_t N // Number of dimensions , typename ET > // Type of the element BLAZE_ALWAYS_INLINE bool tryDiv( const Array& arr, std::array< size_t, N > const& dims, const ET& value ) { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& arrdims = ( ~arr ).dimensions(); ArrayDimForEach( arrdims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); } ); #endif @@ -408,7 +425,7 @@ BLAZE_ALWAYS_INLINE bool #if defined(BLAZE_INTERNAL_ASSERTION) ArrayDimForEach( dims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( currdims[i] < dims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( currdims[i] < dims[i], "Invalid array access index" ); } ); #endif @@ -445,7 +462,7 @@ BLAZE_ALWAYS_INLINE bool tryAssign( const Array& lhs, const Array& rhs, #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); } ); #endif @@ -482,7 +499,7 @@ BLAZE_ALWAYS_INLINE bool tryAddAssign( const Array& lhs, const Array& #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); } ); #endif @@ -519,7 +536,7 @@ BLAZE_ALWAYS_INLINE bool trySubAssign( const Array& lhs, const Array& #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); } ); #endif @@ -557,7 +574,7 @@ BLAZE_ALWAYS_INLINE bool tryMultAssign( const Array& lhs, const Array& #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); } ); #endif @@ -594,7 +611,7 @@ BLAZE_ALWAYS_INLINE bool trySchurAssign( const Array& lhs, const Array #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); } ); #endif @@ -631,7 +648,7 @@ BLAZE_ALWAYS_INLINE bool tryDivAssign( const Array& lhs, const Array& #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i + 1], "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); } ); #endif diff --git a/blaze_tensor/math/expressions/Forward.h b/blaze_tensor/math/expressions/Forward.h index 644ecf6..29da694 100644 --- a/blaze_tensor/math/expressions/Forward.h +++ b/blaze_tensor/math/expressions/Forward.h @@ -51,8 +51,9 @@ namespace blaze { // //================================================================================================= +template< typename > struct Array; +template< typename > struct Tensor; template< typename > struct DenseArray; - template< typename > struct DenseTensor; template< typename > class DTensSerialExpr; @@ -119,6 +120,12 @@ decltype(auto) map( const DenseTensor&, OP ); template< typename TT1, typename TT2, typename OP > decltype(auto) map( const DenseTensor&, const DenseTensor&, OP ); +template< typename TT, typename OP > +decltype(auto) map( const DenseArray&, OP ); + +template< typename TT1, typename TT2, typename OP > +decltype(auto) map( const DenseArray&, const DenseArray&, OP ); + template< typename TT, typename OP > decltype(auto) reduce( const DenseTensor&, OP ); diff --git a/blaze_tensor/math/traits/ArraySliceTrait.h b/blaze_tensor/math/traits/ArraySliceTrait.h new file mode 100644 index 0000000..3dd5678 --- /dev/null +++ b/blaze_tensor/math/traits/ArraySliceTrait.h @@ -0,0 +1,211 @@ +//================================================================================================= +/*! +// \file blaze_array/math/traits/ArraySliceTrait.h +// \brief Header file for the arrayslice trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TRAITS_ARRAYSLICETRAIT_H_ +#define _BLAZE_TENSOR_MATH_TRAITS_ARRAYSLICETRAIT_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t, typename, size_t... > struct ArraySliceTrait; +template< size_t, typename, size_t, typename = void > struct ArraySliceTraitEval1; +template< size_t, typename, size_t, typename = void > struct ArraySliceTraitEval2; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, size_t I, typename T > +auto evalArraySliceTrait( T& ) + -> typename ArraySliceTraitEval1::Type; + +template< size_t M, typename T > +auto evalArraySliceTrait( T& ) + -> typename ArraySliceTraitEval2::Type; + +template< size_t M, size_t I, typename T > +auto evalArraySliceTrait( const T& ) + -> typename ArraySliceTrait::Type; + +template< size_t M, typename T > +auto evalArraySliceTrait( const T& ) + -> typename ArraySliceTrait::Type; + +template< size_t M, size_t I, typename T > +auto evalArraySliceTrait( const volatile T& ) + -> typename ArraySliceTrait::Type; + +template< size_t M, typename T > +auto evalArraySliceTrait( const volatile T& ) + -> typename ArraySliceTrait::Type; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Base template for the ArraySliceTrait class. +// \ingroup math_traits +// +// \section pagetrait_general General +// +// The ArraySliceTrait class template offers the possibility to select the resulting data type when +// creating a view on a specific page of a dense or sparse array. ArraySliceTrait defines the nested +// type \a Type, which represents the resulting data type of the page operation. In case the +// given data type is not a dense or sparse array type, the resulting data type \a Type is +// set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference modifiers +// are generally ignored. +// +// +// \section pagetrait_specializations Creating custom specializations +// +// Per default, ArraySliceTrait supports all array types of the Blaze library (including views and +// adaptors). For all other data types it is possible to specialize the ArraySliceTrait template. The +// following example shows the according specialization for the DynamicArray class template: + + \code + template< size_t M, typename T1, size_t... CRAs > + struct ArraySliceTrait< M, DynamicArray, CRAs... > + { + using Type = DynamicArray; + }; + \endcode + +// \n \section arrayslicetrait_examples Examples +// +// The following example demonstrates the use of the ArraySliceTrait template, where depending on +// the given array type the resulting page type is selected: + + \code + // Definition of the page type of a dynamic array + using ArrayType1 = blaze::DynamicArray<3,int>; + using ResultType1 = typename blaze::ArraySliceTrait<3,ArrayType1>::Type; + \endcode +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time page arguments +struct ArraySliceTrait +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = decltype( evalArraySliceTrait( std::declval() ) ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary alias declaration for the ArraySliceTrait type trait. +// \ingroup math_traits +// +// The ArraySliceTrait_t alias declaration provides a convenient shortcut to access the nested +// \a Type of the ArraySliceTrait class template. For instance, given the array type \a MT the +// following two type definitions are identical: + + \code + using Type1 = typename blaze::ArraySliceTrait::Type; + using Type2 = blaze::ArraySliceTrait_t; + \endcode +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time page arguments +using ArraySliceTrait_t = typename ArraySliceTrait::Type; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief First auxiliary helper struct for the ArraySliceTrait type trait. +// \ingroup math_traits +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t I // Compile time dimensional index + , typename > // Restricting condition +struct ArraySliceTraitEval1 +{ + public: + //********************************************************************************************** + using Type = typename ArraySliceTraitEval2::Type; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Second auxiliary helper struct for the ArraySliceTrait type trait. +// \ingroup math_traits +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t I // Compile time dimensional index + , typename > // Restricting condition +struct ArraySliceTraitEval2 +{ + public: + //********************************************************************************************** + using Type = INVALID_TYPE; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsArraySlice.h b/blaze_tensor/math/typetraits/IsArraySlice.h new file mode 100644 index 0000000..b5e4705 --- /dev/null +++ b/blaze_tensor/math/typetraits/IsArraySlice.h @@ -0,0 +1,168 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/typetraits/IsArraySlice.h +// \brief Header file for the IsArraySlice type trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAYSLICE_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAYSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Compile time check for arrayslices. +// \ingroup math_type_traits +// +// This type trait tests whether or not the given template parameter is a arrayslice (i.e. a view on a +// arrayslice of a dense or sparse matrix). In case the type is a arrayslice, the \a value member constant is +// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from +// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class +// derives from \a FalseType. + + \code + using blaze::aligned; + + using MatrixType1 = blaze::StaticMatrix; + using MatrixType2 = blaze::DynamicArray<3, double>; + using MatrixType3 = blaze::CompressedMatrix; + + MatrixType1 A; + MatrixType2 B( 100UL, 200UL ); + MatrixType3 C( 200UL, 250UL ); + + using ArraySliceType1 = decltype( blaze::arrayslice<1, 4UL>( A ) ); + using ArraySliceType2 = decltype( blaze::arrayslice<1>( B, 16UL ) ); + using ArraySliceType3 = decltype( blaze::arrayslice<1>( C, 17UL ) ); + + blaze::IsArraySlice< 1, ArraySliceType1 >::value // Evaluates to 1 + blaze::IsArraySlice< 1, const ArraySliceType2 >::Type // Results in TrueType + blaze::IsArraySlice< 1, volatile ArraySliceType3 > // Is derived from TrueType + blaze::IsArraySlice< 1, MatrixType1 >::value // Evaluates to 0 + blaze::IsArraySlice< 1, const MatrixType2 >::Type // Results in FalseType + blaze::IsArraySlice< 1, volatile MatrixType3 > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsArraySlice + : public FalseType +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsArraySlice type trait for 'ArraySlice'. +// \ingroup math_type_traits +*/ +template< size_t M, typename MT, size_t... CRAs > +struct IsArraySlice< ArraySlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsArraySlice type trait for 'const ArraySlice'. +// \ingroup math_type_traits +*/ +template< size_t M, typename MT, size_t... CRAs > +struct IsArraySlice< const ArraySlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsArraySlice type trait for 'volatile ArraySlice'. +// \ingroup math_type_traits +*/ +template< size_t M, typename MT, size_t... CRAs > +struct IsArraySlice< volatile ArraySlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsArraySlice type trait for 'const volatile ArraySlice'. +// \ingroup math_type_traits +*/ +template< size_t M, typename MT, size_t... CRAs > +struct IsArraySlice< const volatile ArraySlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary variable template for the IsArraySlice type trait. +// \ingroup type_traits +// +// The IsArraySlice_v variable template provides a convenient shortcut to access the nested \a value +// of the IsArraySlice class template. For instance, given the type \a T the following two statements +// are identical: + + \code + constexpr bool value1 = blaze::IsArraySlice<3,T>::value; + constexpr bool value2 = blaze::IsArraySlice_v<4,T>; + \endcode +*/ +template< typename T > +constexpr bool IsArraySlice_v = IsArraySlice::value; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/ArraySlice.h b/blaze_tensor/math/views/ArraySlice.h new file mode 100644 index 0000000..2a4ad48 --- /dev/null +++ b/blaze_tensor/math/views/ArraySlice.h @@ -0,0 +1,1634 @@ +//================================================================================================= +/*! +// \file blaze_array/math/views/ArraySlice.h +// \brief Header file for the implementation of the ArraySlice view +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include +#include +// #include +// #include +// #include +#include +#include +#include +#include +// #include +// #include +// #include +#include +#include +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Creating a view on a specific arrayslice of the given array. +// \ingroup arrayslice +// +// \param array The array containing the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the array. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given array. + + \code + blaze::DynamicArray D; + blaze::CompressedArray S; + // ... Resizing and initialization + + // Creating a view on the 3rd arrayslice of the dense array D along dimension 0 + auto arrayslice3 = arrayslice<0UL,3UL>( D ); + + // Creating a view on the 4th arrayslice of the sparse array S along dimension 2 + auto arrayslice4 = arrayslice<2UL,4UL>( S ); + \page() + +// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices +// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto arrayslice3 = arrayslice<0UL,3UL>( D, unchecked ); + auto arrayslice4 = arrayslice<0UL,4UL>( S, unchecked ); + \page() +*/ +template< size_t M // ArraySlice dimension + , size_t I // ArraySlice index + , typename MT // Type of the array + , typename... RRAs > // Optional arrayslice arguments +inline decltype(auto) arrayslice( Array& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = ArraySlice_; + return ReturnType( ~array, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific arrayslice of the given constant array. +// \ingroup arrayslice +// +// \param array The constant array containing the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the array. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given constant +// array. + + \code + + const blaze::DynamicArray D( ... ); + const blaze::CompressedArray S( ... ); + + // Creating a view on the 3rd arrayslice of the dense array D + auto arrayslice3 = arrayslice<0UL,3UL>( D ); + + // Creating a view on the 4th arrayslice of the sparse array S + auto arrayslice4 = arrayslice<0UL,4UL>( S ); + \page() + +// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices +// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto arrayslice3 = arrayslice<0UL,3UL>( D, unchecked ); + auto arrayslice4 = arrayslice<0UL,4UL>( S, unchecked ); + \page() +*/ +template< size_t M // ArraySlice dimension + , size_t I // ArraySlice index + , typename MT // Type of the array + , typename... RRAs > // Optional arrayslice arguments +inline decltype(auto) arrayslice( const Array& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const ArraySlice_; + return ReturnType( ~array, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific arrayslice of the given temporary array. +// \ingroup arrayslice +// +// \param array The temporary array containing the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the array. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given temporary +// array. In case the arrayslice is not properly specified (i.e. if the specified index is greater +// than or equal to the total number of the arrayslices in the given array) a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // ArraySlice dimension + , size_t I // ArraySlice index + , typename MT // Type of the array + , typename... RRAs > // Optional arrayslice arguments +inline decltype(auto) arrayslice( Array&& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = ArraySlice_; + return ReturnType( ~array, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific arrayslice of the given array. +// \ingroup arrayslice +// +// \param array The array containing the arrayslice. +// \param index The index of the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the array. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given array. + + \code + blaze::DynamicArray D; + blaze::CompressedArray S; + // ... Resizing and initialization + + // Creating a view on the 3rd arrayslice of the dense array D along dimension 1 + auto arrayslice3 = arrayslice<1UL>( D, 3UL ); + + // Creating a view on the 4th arrayslice of the sparse array S along dimension 2 + auto arrayslice4 = arrayslice<2UL>( S, 4UL ); + \page() + +// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices +// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto arrayslice3 = arrayslice<0UL>( D, 3UL, unchecked ); + auto arrayslice4 = arrayslice<0UL>( S, 4UL, unchecked ); + \page() +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , typename... RRAs > // Optional arrayslice arguments +inline decltype(auto) arrayslice( Array& array, size_t index, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = ArraySlice_; + return ReturnType( ~array, index, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific arrayslice of the given constant array. +// \ingroup arrayslice +// +// \param array The constant array containing the arrayslice. +// \param index The index of the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the array. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given constant +// array. + + \code + const blaze::DynamicArray D( ... ); + const blaze::CompressedArray S( ... ); + + // Creating a view on the 3rd arrayslice of the dense array D + auto arrayslice3 = arrayslice( D, 3UL ); + + // Creating a view on the 4th arrayslice of the sparse array S + auto arrayslice4 = arrayslice( S, 4UL ); + \page() + +// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices +// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto arrayslice3 = arrayslice( D, 3UL, unchecked ); + auto arrayslice4 = arrayslice( S, 4UL, unchecked ); + \page() +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , typename... RRAs > // Optional arrayslice arguments +inline decltype(auto) arrayslice( const Array& array, size_t index, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const ArraySlice_; + return ReturnType( ~array, index, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific arrayslice of the given temporary array. +// \ingroup arrayslice +// +// \param array The temporary array containing the arrayslice. +// \param index The index of the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the array. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given temporary +// array. In case the arrayslice is not properly specified (i.e. if the specified index is greater +// than or equal to the total number of the arrayslices in the given array) a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , typename... RRAs > // Optional arrayslice arguments +inline decltype(auto) arrayslice( Array&& array, size_t index, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = ArraySlice_; + return ReturnType( ~array, index, args... ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array/array addition. +// \ingroup arrayslice +// +// \param array The constant array/array addition. +// \param args The runtime arrayslice arguments. +// \return View on the specified arrayslice of the addition. +// +// This function returns an expression representing the specified arrayslice of the given array/array +// addition. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const ArrArrAddExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( (~array).leftOperand(), args... ) + +// arrayslice( (~array).rightOperand(), args... ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array/array subtraction. +// \ingroup arrayslice +// +// \param array The constant array/array subtraction. +// \param args The runtime arrayslice arguments. +// \return View on the specified arrayslice of the subtraction. +// +// This function returns an expression representing the specified arrayslice of the given array/array +// subtraction. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const ArrArrSubExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( (~array).leftOperand(), args... ) - +// arrayslice( (~array).rightOperand(), args... ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given Schur product. +// \ingroup arrayslice +// +// \param array The constant Schur product. +// \param args The runtime arrayslice arguments. +// \return View on the specified arrayslice of the Schur product. +// +// This function returns an expression representing the specified arrayslice of the given Schur product. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const SchurExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( (~array).leftOperand(), args... ) * +// arrayslice( (~array).rightOperand(), args... ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array/array multiplication. +// \ingroup arrayslice +// +// \param array The constant array/array multiplication. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the multiplication. +// +// This function returns an expression representing the specified arrayslice of the given array/array +// multiplication. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const ArrArrMultExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( (~array).leftOperand(), args... ) * (~array).rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given outer product. +// \ingroup arrayslice +// +// \param array The constant outer product. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the outer product. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given outer product. +*/ +// template< size_t I // ArraySlice index +// , typename MT // Array base type of the expression +// , typename... RRAs > // Optional arrayslice arguments +// inline decltype(auto) arrayslice( const VecTVecMultExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// MAYBE_UNUSED( args... ); +// +// if( !Contains_v< TypeList, Unchecked > ) { +// if( (~array).arrayslices() <= I ) { +// BLAZE_THARRAYSLICE_INVALID_ARGUMENT( "Invalid arrayslice access index" ); +// } +// } +// +// return (~array).leftOperand()[I] * (~array).rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given outer product. +// \ingroup arrayslice +// +// \param array The constant outer product. +// \param index The index of the arrayslice. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the outer product. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// This function returns an expression representing the specified arrayslice of the given outer product. +*/ +// template< typename MT // Array base type of the expression +// , typename... RRAs > // Optional arrayslice arguments +// inline decltype(auto) arrayslice( const VecTVecMultExpr& array, size_t index, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// MAYBE_UNUSED( args... ); +// +// if( !Contains_v< TypeList, Unchecked > ) { +// if( (~array).arrayslices() <= index ) { +// BLAZE_THARRAYSLICE_INVALID_ARGUMENT( "Invalid arrayslice access index" ); +// } +// } +// +// return (~array).leftOperand()[index] * (~array).rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array/scalar multiplication. +// \ingroup arrayslice +// +// \param array The constant array/scalar multiplication. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the multiplication. +// +// This function returns an expression representing the specified arrayslice of the given array/scalar +// multiplication. +*/ +template< size_t... CRAs // Compile time arrayslice arguments + , typename MT // Array base type of the expression + , typename... RRAs > // Runtime arrayslice arguments +inline decltype(auto) arrayslice( const ArrScalarMultExpr& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return arrayslice( (~array).leftOperand(), args... ) * (~array).rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array/scalar division. +// \ingroup arrayslice +// +// \param array The constant array/scalar division. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the division. +// +// This function returns an expression representing the specified arrayslice of the given array/scalar +// division. +*/ +template< size_t... CRAs // Compile time arrayslice arguments + , typename MT // Array base type of the expression + , typename... RRAs > // Runtime arrayslice arguments +inline decltype(auto) arrayslice( const ArrScalarDivExpr& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return arrayslice( (~array).leftOperand(), args... ) / (~array).rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given unary array map operation. +// \ingroup arrayslice +// +// \param array The constant unary array map operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the unary map operation. +// +// This function returns an expression representing the specified arrayslice of the given unary array +// map operation. +*/ +template< size_t... CRAs // Compile time arrayslice arguments + , typename MT // Array base type of the expression + , typename... RRAs > // Runtime arrayslice arguments +inline decltype(auto) arrayslice( const ArrMapExpr& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return map( arrayslice( (~array).operand(), args... ), (~array).operation() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given binary array map operation. +// \ingroup arrayslice +// +// \param array The constant binary array map operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the binary map operation. +// +// This function returns an expression representing the specified arrayslice of the given binary array +// map operation. +*/ +template< size_t... CRAs // Compile time arrayslice arguments + , typename MT // Array base type of the expression + , typename... RRAs > // Runtime arrayslice arguments +inline decltype(auto) arrayslice( const ArrArrMapExpr& array, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return map( arrayslice( (~array).leftOperand(), args... ), + arrayslice( (~array).rightOperand(), args... ), + (~array).operation() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array evaluation operation. +// \ingroup arrayslice +// +// \param array The constant array evaluation operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the evaluation operation. +// +// This function returns an expression representing the specified arrayslice of the given array +// evaluation operation. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const ArrEvalExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return eval( arrayslice( (~array).operand(), args... ) ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array serialization operation. +// \ingroup arrayslice +// +// \param array The constant array serialization operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the serialization operation. +// +// This function returns an expression representing the specified arrayslice of the given array +// serialization operation. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const ArrSerialExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return serial( arrayslice( (~array).operand(), args... ) ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array declaration operation. +// \ingroup arrayslice +// +// \param array The constant array declaration operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the declaration operation. +// +// This function returns an expression representing the specified arrayslice of the given array +// declaration operation. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const DeclExpr& array, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( (~array).operand(), args... ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array transpose operation. +// \ingroup arrayslice +// +// \param array The constant array transpose operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the transpose operation. +// +// This function returns an expression representing the specified arrayslice of the given array +// transpose operation. +*/ +// template< size_t MK // Compile time arrayslice arguments +// , size_t MI +// , size_t MJ +// , typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arguments +// inline decltype(auto) arrayslice( const ArrTransExpr& array, size_t index, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( evaluate( ~array ), index, args... ); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given array transpose operation. +// \ingroup arrayslice +// +// \param array The constant array transpose operation. +// \param args The runtime arrayslice arguments +// \return View on the specified arrayslice of the transpose operation. +// +// This function returns an expression representing the specified arrayslice of the given array +// transpose operation. +*/ +// template< typename MT // Array base type of the expression +// , typename... RRAs > // Runtime arguments +// inline decltype(auto) arrayslice( const ArrTransExpr& array, size_t index, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return arrayslice( evaluate( ~array ), index, args... ); +// } +/*! \endcond */ +//************************************************************************************************* + + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific arrayslice of the given matrix expansion operation. +// \ingroup subarray +// +// \param array The constant matrix expansion operation. +// \param args Optional arrayslice arguments. +// \return View on the specified arrayslice of the expansion operation. +// +// This function returns an expression representing the specified arrayslice of the given matrix +// expansion operation. +*/ +// template< size_t... CRAs // Compile time arrayslice arguments +// , typename MT // Matrix base type of the expression +// , size_t... CEAs // Compile time expansion arguments +// , typename... RSAs > // Runtime arrayslice arguments +// inline decltype(auto) arrayslice( const MatExpandExpr& array, RSAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// MAYBE_UNUSED( args... ); +// +// return submatrix( (~array).operand(), 0UL, 0UL, (~array).rows(), (~array).columns() ); +// } +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING FUNCTIONS (ROW) +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a selection of row of the given array/vector multiplication. +// \ingroup arrayslice +// +// \param matrix The constant array/vector multiplication. +// \param args The runtime element arguments. +// \return View on the specified row of the multiplication. +// +// This function returns an expression representing the specified elements of the given +// matrix/vector multiplication. +*/ +// template< size_t... CEAs // Compile time element arguments +// , typename MT // Matrix base type of the expression +// , typename... REAs > // Runtime element arguments +// inline decltype(auto) row( const ArrVecMultExpr& matrix, REAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// return trans(arrayslice( (~matrix).leftOperand(), args... ) * (~matrix).rightOperand()); +// } +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ARRAYSLICE OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Resetting the given arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The arrayslice to be resetted. +// \return void +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time arrayslice arguments +inline void reset( ArraySlice& arrayslice ) +{ + arrayslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Resetting the given temporary arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The temporary arrayslice to be resetted. +// \return void +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time arrayslice arguments +inline void reset( ArraySlice&& arrayslice ) +{ + arrayslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Clearing the given arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The arrayslice to be cleared. +// \return void +// +// Clearing a arrayslice is equivalent to resetting it via the reset() function. +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time arrayslice arguments +inline void clear( ArraySlice& arrayslice ) +{ + arrayslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Clearing the given temporary arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The temporary arrayslice to be cleared. +// \return void +// +// Clearing a arrayslice is equivalent to resetting it via the reset() function. +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time arrayslice arguments +inline void clear( ArraySlice&& arrayslice ) +{ + arrayslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the given dense arrayslice is in default state. +// \ingroup arrayslice +// +// \param arrayslice The dense arrayslice to be tested for its default state. +// \return \a true in case the given dense arrayslice is component-wise zero, \a false otherwise. +// +// This function checks whether the dense arrayslice is in default state. For instance, in case the +// arrayslice is instantiated for a built-in integral or floating point data type, the function returns +// \a true in case all arrayslice elements are 0 and \a false in case any arrayslice element is not 0. The +// following example demonstrates the use of the \a isDefault function: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + if( isDefault( arrayslice( A, 0UL ) ) ) { ... } + \page() + +// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed +// semantics (blaze::relaxed): + + \code + if( isDefault( arrayslice( A, 0UL ) ) ) { ... } + \page() +*/ +template< bool RF // Relaxation flag + , size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time arrayslice arguments +inline bool isDefault( const ArraySlice& arrayslice ) +{ + using blaze::isDefault; + + constexpr size_t N = ArraySlice::num_dimensions(); + + return ArrayForEachGroupedAllOf( + arrayslice.dimensions(), [&]( std::array< size_t, N > const& indices ) { + return isDefault( arrayslice( indices ) ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the invariants of the given arrayslice are intact. +// \ingroup arrayslice +// +// \param arrayslice The arrayslice to be tested. +// \return \a true in case the given arrayslice's invariants are intact, \a false otherwise. +// +// This function checks whether the invariants of the arrayslice are intact, i.e. if its state is valid. +// In case the invariants are intact, the function returns \a true, else it will return \a false. +// The following example demonstrates the use of the \a isIntact() function: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + if( isIntact( arrayslice( A, 0UL ) ) ) { ... } + \page() +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs > // Compile time arrayslice arguments +inline bool isIntact( const ArraySlice& arrayslice ) noexcept +{ + return ( arrayslice.index() < arrayslice.operand().template dimensions() && + isIntact( arrayslice.operand() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the two given arrayslices represent the same observable state. +// \ingroup arrayslice +// +// \param a The first arrayslice to be tested for its state. +// \param b The second arrayslice to be tested for its state. +// \return \a true in case the two arrayslices share a state, \a false otherwise. +// +// This overload of the isSame() function tests if the two given arrayslices refer to exactly the same +// range of the same array. In case both arrayslices represent the same observable state, the function +// returns \a true, otherwise it returns \a false. +*/ +template< size_t M1 // ArraySlice dimension + , typename MT1 // Type of the array of the left-hand side arrayslice + , size_t... CRAs1 // Compile time arrayslice arguments of the left-hand side arrayslice + , size_t M2 // ArraySlice dimension + , typename MT2 // Type of the array of the right-hand side arrayslice + , size_t... CRAs2 > // Compile time arrayslice arguments of the right-hand side arrayslice +inline bool isSame( const ArraySlice& a, + const ArraySlice& b ) noexcept +{ + return ( M1 == M2 && isSame( a.operand(), b.operand() ) && ( a.index() == b.index() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by setting a single element of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param i The row to be set. +// \param j The column to be set. +// \param value The value to be set to the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Number of dimensions + , typename ET > // Type of the element +inline bool trySet( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) +{ + constexpr size_t array_N = ( ~arrayslice.operand() ).num_dimensions(); + BLAZE_STATIC_ASSERT( N + 1 == array_N ); + + return trySet( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by adding to a single element of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param i The row to be modified. +// \param j The column to be modified. +// \param value The value to be added to the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename ET > // Type of the element +inline bool tryAdd( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) +{ + constexpr size_t array_N = ( ~arrayslice.operand() ).num_dimensions(); + BLAZE_STATIC_ASSERT( N + 1 == array_N ); + + return tryAdd( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by subtracting from a single element of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param i The row to be modified. +// \param j The column to be modified. +// \param value The value to be subtracted from the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename ET > // Type of the element +inline bool trySub( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < arrayslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < arrayslice.columns(), "Invalid column access index" ); + + return trySub( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a single element of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param i The row to be modified. +// \param j The column to be modified. +// \param value The factor for the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename ET > // Type of the element +inline bool tryMult( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < arrayslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < arrayslice.columns(), "Invalid column access index" ); + + return tryMult( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a range of elements of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param index The index of the first element of the range to be modified. +// \param size The number of elements of the range to be modified. +// \param value The factor for the elements. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool + tryMult( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, std::array< size_t, N > const& sizes, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( row <= (~arrayslice).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( row + rows <= (~arrayslice).rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( col <= (~arrayslice).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( col + cols <= (~arrayslice).columns(), "Invalid columns range size" ); + + return tryMult( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), mergeDims( sizes, 1UL ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a single element of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param index The index of the element to be modified. +// \param value The divisor for the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename ET > // Type of the element +inline bool tryDiv( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( i < arrayslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < arrayslice.columns(), "Invalid column access index" ); + + return tryDiv( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a range of elements of a arrayslice. +// \ingroup arrayslice +// +// \param arrayslice The target arrayslice. +// \param index The index of the first element of the range to be modified. +// \param size The number of elements of the range to be modified. +// \param value The divisor for the elements. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool + tryDiv( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, std::array< size_t, N > const& sizes, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( row <= (~arrayslice).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( row + rows <= (~arrayslice).rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( col <= (~arrayslice).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( col + cols <= (~arrayslice).columns(), "Invalid columns range size" ); + + return tryDiv( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), mergeDims( sizes, 1UL ), value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the assignment of a matrix to a arrayslice. +// \ingroup arrayslice +// +// \param lhs The target left-hand side arrayslice. +// \param rhs The right-hand side vector to be assigned. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename VT > // Type of the right-hand side matrix +inline bool tryAssign( const ArraySlice& lhs, + const Matrix& rhs, std::array< size_t, N > const& dims ) +{ + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the addition assignment of a vector to a arrayslice. +// \ingroup arrayslice +// +// \param lhs The target left-hand side arrayslice. +// \param rhs The right-hand side vector to be added. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename VT > // Type of the right-hand side matrix +inline bool tryAddAssign( const ArraySlice& lhs, + const Matrix& rhs, std::array< size_t, N > const& dims ) +{ + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryAddAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the subtraction assignment of a vector to a arrayslice. +// \ingroup arrayslice +// +// \param lhs The target left-hand side arrayslice. +// \param rhs The right-hand side vector to be subtracted. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename VT > // Type of the right-hand side matrix +inline bool trySubAssign( const ArraySlice& lhs, + const Matrix& rhs, std::array< size_t, N > const& dims ) +{ + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return trySubAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the multiplication assignment of a vector to a arrayslice. +// \ingroup arrayslice +// +// \param lhs The target left-hand side arrayslice. +// \param rhs The right-hand side vector to be multiplied. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename VT > // Type of the right-hand side matrix +inline bool tryMultAssign( const ArraySlice& lhs, + const Vector& rhs, std::array< size_t, N > const& dims ) +{ + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryMultAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the division assignment of a vector to a arrayslice. +// \ingroup arrayslice +// +// \param lhs The target left-hand side arrayslice. +// \param rhs The right-hand side vector divisor. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the array + , size_t... CRAs // Compile time arrayslice arguments + , size_t N // Dimensions of the ArraysSlice + , typename VT > // Type of the right-hand side matrix +inline bool tryDivAssign( const ArraySlice& lhs, + const Matrix& rhs, std::array< size_t, N > const& dims ) +{ + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryDivAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given arrayslice. +// \ingroup arrayslice +// +// \param r The arrayslice to be derestricted. +// \return ArraySlice without access restrictions. +// +// This function removes all restrictions on the data access to the given arrayslice. It returns a arrayslice +// object that does provide the same interface but does not have any restrictions on the data +// access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t I > // ArraySlice index +inline decltype(auto) derestrict( ArraySlice& r ) +{ + return arrayslice( derestrict( r.operand() ), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given temporary arrayslice. +// \ingroup arrayslice +// +// \param r The temporary arrayslice to be derestricted. +// \return ArraySlice without access restrictions. +// +// This function removes all restrictions on the data access to the given temporary arrayslice. It +// returns a arrayslice object that does provide the same interface but does not have any restrictions +// on the data access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< size_t M // ArraySlice dimension + , typename MT // Type of the array + , size_t I > // ArraySlice index +inline decltype(auto) derestrict( ArraySlice&& r ) +{ + return arrayslice( derestrict( r.operand() ), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given arrayslice. +// \ingroup arrayslice +// +// \param r The arrayslice to be derestricted. +// \return ArraySlice without access restrictions. +// +// This function removes all restrictions on the data access to the given arrayslice. It returns a arrayslice +// object that does provide the same interface but does not have any restrictions on the data +// access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< size_t M // ArraySlice dimension + , typename MT > // ArraySlice index +inline decltype(auto) derestrict( ArraySlice& r ) +{ + return arrayslice( derestrict( r.operand() ), r.index(), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given temporary arrayslice. +// \ingroup arrayslice +// +// \param r The temporary arrayslice to be derestricted. +// \return ArraySlice without access restrictions. +// +// This function removes all restrictions on the data access to the given temporary arrayslice. It +// returns a arrayslice object that does provide the same interface but does not have any restrictions +// on the data access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< size_t M // ArraySlice dimension + , typename MT > // ArraySlice index +inline decltype(auto) derestrict( ArraySlice&& r ) +{ + return arrayslice( derestrict( r.operand() ), r.index(), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs, size_t Index > +struct Size< ArraySlice< M, MT, CRAs... >, Index > + : public Size< MT, ( Index < M ) ? Index : Index + 1 > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MAXSIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs, size_t Index > +struct MaxSize< ArraySlice< M, MT, CRAs... >, Index > + : public MaxSize< MT, ( Index < M ) ? Index : Index + 1 > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs > +struct IsRestricted< ArraySlice > + : public IsRestricted +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs > +struct HasConstDataAccess< ArraySlice > + : public HasConstDataAccess +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs > +struct HasMutableDataAccess< ArraySlice > + : public HasMutableDataAccess +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs > +struct IsAligned< ArraySlice > + : public BoolConstant< IsAligned_v > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCONTIGUOUS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs > +struct IsContiguous< ArraySlice > + : public IsContiguous +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t M, typename MT, size_t... CRAs > +struct IsPadded< ArraySlice > + : public BoolConstant< IsPadded_v > +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/Forward.h b/blaze_tensor/math/views/Forward.h index 92a2e4b..f7d11a7 100644 --- a/blaze_tensor/math/views/Forward.h +++ b/blaze_tensor/math/views/Forward.h @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -248,6 +249,24 @@ inline decltype(auto) dilatedsubtensor( Subtensor&& st, // template< typename TT, typename T, typename... RCAs > // decltype(auto) columns( Tensor&&, const T*, size_t, RCAs... ); +template< size_t I, typename TT, typename... RRAs > +decltype(auto) columnslice( Tensor&, RRAs... ); + +template< size_t I, typename TT, typename... RRAs > +decltype(auto) columnslice( const Tensor&, RRAs... ); + +template< size_t I, typename TT, typename... RRAs > +decltype(auto) columnslice( Tensor&&, RRAs... ); + +template< typename TT, typename... RRAs > +decltype(auto) columnslice( Tensor&, size_t, RRAs... ); + +template< typename TT, typename... RRAs > +decltype(auto) columnslice( const Tensor&, size_t, RRAs... ); + +template< typename TT, typename... RRAs > +decltype(auto) columnslice( Tensor&&, size_t, RRAs... ); + template< size_t I, typename TT, typename... RRAs > decltype(auto) pageslice( Tensor&, RRAs... ); @@ -266,6 +285,42 @@ decltype(auto) pageslice( const Tensor&, size_t, RRAs... ); template< typename TT, typename... RRAs > decltype(auto) pageslice( Tensor&&, size_t, RRAs... ); +template< size_t I, typename TT, typename... RRAs > +decltype(auto) rowslice( Tensor&, RRAs... ); + +template< size_t I, typename TT, typename... RRAs > +decltype(auto) rowslice( const Tensor&, RRAs... ); + +template< size_t I, typename TT, typename... RRAs > +decltype(auto) rowslice( Tensor&&, RRAs... ); + +template< typename TT, typename... RRAs > +decltype(auto) rowslice( Tensor&, size_t, RRAs... ); + +template< typename TT, typename... RRAs > +decltype(auto) rowslice( const Tensor&, size_t, RRAs... ); + +template< typename TT, typename... RRAs > +decltype(auto) rowslice( Tensor&&, size_t, RRAs... ); + +template< size_t M, size_t I, typename AT, typename... RRAs > +decltype(auto) arrayslice( Array&, RRAs... ); + +template< size_t M, size_t I, typename AT, typename... RRAs > +decltype(auto) arrayslice( const Array&, RRAs... ); + +template< size_t M, size_t I, typename AT, typename... RRAs > +decltype(auto) arrayslice( Array&&, RRAs... ); + +template< size_t M, typename AT, typename... RRAs > +decltype(auto) arrayslice( Array&, size_t, RRAs... ); + +template< size_t M, typename AT, typename... RRAs > +decltype(auto) arrayslice( const Array&, size_t, RRAs... ); + +template< size_t M, typename AT, typename... RRAs > +decltype(auto) arrayslice( Array&&, size_t, RRAs... ); + // template< size_t I, size_t... Is, typename TT, typename... RCAs > // decltype(auto) pages( Tensor&, RCAs... ); // diff --git a/blaze_tensor/math/views/arrayslice/ArraySlice.h b/blaze_tensor/math/views/arrayslice/ArraySlice.h new file mode 100644 index 0000000..f0ddff4 --- /dev/null +++ b/blaze_tensor/math/views/arrayslice/ArraySlice.h @@ -0,0 +1,328 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/views/pageslice/PageSlice.h +// \brief PageSlice documentation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_PAGESLICE_PAGESLICE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_PAGESLICE_PAGESLICE_H_ + + +//================================================================================================= +// +// DOXYGEN DOCUMENTATION +// +//================================================================================================= + +//************************************************************************************************* +/*!\defgroup pageslice PageSlice +// \ingroup views +// +// PageSlices provide views on a specific pageslice of a dense or sparse tensor. As such, pageslices act as a +// reference to a specific pageslice. This reference is valid and can be used in every way any other +// pageslice matrix can be used as long as the tensor containing the pageslice is not resized or entirely +// destroyed. The pageslice also acts as an alias to the pageslice elements: Changes made to the elements +// (e.g. modifying values, inserting or erasing elements) are immediately visible in the tensor +// and changes made via the tensor are immediately visible in the pageslice. +// +// +// \n \section pageslice_setup Setup of PageSlices +// +// \image html pageslice.png +// \image latex pageslice.eps "PageSlice view" width=250pt +// +// A reference to a dense or sparse pageslice can be created very conveniently via the \c pageslice() function. +// It can be included via the header file + + \code + #include + \endcode + +// The pageslice index must be in the range from \f$[0..M-1]\f$, where \c M is the total number of pageslices +// of the tensor, and can be specified both at compile time or at runtime: + + \code + blaze::DynamicTensor A; + // ... Resizing and initialization + + // Creating a reference to the 1st pageslice of tensor A (compile time index) + auto pageslice1 = pageslice<1UL>( A ); + + // Creating a reference to the 2nd pageslice of tensor A (runtime index) + auto pageslice2 = pageslice( A, 2UL ); + \endcode + +// The \c pageslice() function returns an expression representing the pageslice view. The type of this +// expression depends on the given pageslice arguments, primarily the type of the tensor and the compile +// time arguments. If the type is required, it can be determined via \c decltype specifier: + + \code + using TensorType = blaze::DynamicTensor; + using PageSliceType = decltype( blaze::pageslice<1UL>( std::declval() ) ); + \endcode + +// The resulting view can be treated as any other pageslice matrix, i.e. it can be assigned to, it can +// be copied from, and it can be used in arithmetic operations. The reference can also be used on +// both sides of an assignment: The pageslice can either be used as an alias to grant write access to a +// specific pageslice of a tensor primitive on the left-hand side of an assignment or to grant read-access +// to a specific pageslice of a tensor primitive or expression on the right-hand side of an assignment. +// The following example demonstrates this in detail: + + \code + blaze::DynamicMatrix x; + blaze::DynamicTensor A, B; + // ... Resizing and initialization + + // Setting the 2nd pageslice of tensor A to x + auto pageslice2 = pageslice( A, 2UL ); + pageslice2 = x; + + // Setting the 3rd pageslice of tensor B to x + pageslice( B, 3UL ) = x; + + // Setting x to the 4th pageslice of the result of the tensor multiplication + x = pageslice( A * B, 4UL ); + \endcode + +// \n \section pageslice_element_access Element access +// +// The elements of a pageslice can be directly accessed with the subscript operator: + + \code + blaze::DynamicTensor A; + // ... Resizing and initialization + + // Creating a view on the 4th pageslice of tensor A + auto pageslice4 = pageslice( A, 4UL ); + + // Setting the 1st element of the dense pageslice, which corresponds + // to the 1st element in the 4th pageslice of tensor A + pageslice4(0, 0) = 2.0; + \endcode + +// The numbering of the pageslice elements is + + \f[\left(\begin{array}{*{5}{c}} + 0 & 1 & 2 & \cdots & N-1 \\ + \end{array}\right),\f] + +// where N is the number of columns of the referenced tensor. Alternatively, the elements of a +// pageslice can be traversed via iterators. Just as with vectors, in case of non-const pageslices, \c begin() +// and \c end() return an iterator, which allows to manipulate the elements, in case of constant +// pageslices an iterator to immutable elements is returned: + + \code + blaze::DynamicTensor A( 128UL, 256UL ); + // ... Resizing and initialization + + // Creating a reference to the 31st pageslice of tensor A + auto pageslice31 = pageslice( A, 31UL ); + + // Traversing the elements via iterators to non-const elements + for( auto it=pageslice31.begin(); it!=pageslice31.end(); ++it ) { + *it = ...; // OK; Write access to the dense pageslice value + ... = *it; // OK: Read access to the dense pageslice value. + } + + // Traversing the elements via iterators to const elements + for( auto it=pageslice31.cbegin(); it!=pageslice31.cend(); ++it ) { + *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. + ... = *it; // OK: Read access to the dense pageslice value. + } + \endcode + + \code + blaze::CompressedMatrix A( 128UL, 256UL ); + // ... Resizing and initialization + + // Creating a reference to the 31st pageslice of tensor A + auto pageslice31 = pageslice( A, 31UL ); + + // Traversing the elements via iterators to non-const elements + for( auto it=pageslice31.begin(); it!=pageslice31.end(); ++it ) { + it->value() = ...; // OK: Write access to the value of the non-zero element. + ... = it->value(); // OK: Read access to the value of the non-zero element. + it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. + ... = it->index(); // OK: Read access to the index of the sparse element. + } + + // Traversing the elements via iterators to const elements + for( auto it=pageslice31.cbegin(); it!=pageslice31.cend(); ++it ) { + it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. + ... = it->value(); // OK: Read access to the value of the non-zero element. + it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. + ... = it->index(); // OK: Read access to the index of the sparse element. + } + \endcode + +// \n \section sparse_pageslice_element_insertion Element Insertion +// +// Inserting/accessing elements in a sparse pageslice can be done by several alternative functions. +// The following example demonstrates all options: + + \code + blaze::CompressedMatrix A( 10UL, 100UL ); // Non-initialized 10x100 tensor + + auto pageslice0( pageslice( A, 0UL ) ); // Reference to the 0th pageslice of A + + // The subscript operator provides access to all possible elements of the sparse pageslice, + // including the zero elements. In case the subscript operator is used to access an element + // that is currently not stored in the sparse pageslice, the element is inserted into the pageslice. + pageslice0[42] = 2.0; + + // The second operation for inserting elements is the set() function. In case the element + // is not contained in the pageslice it is inserted into the pageslice, if it is already contained in + // the pageslice its value is modified. + pageslice0.set( 45UL, -1.2 ); + + // An alternative for inserting elements into the pageslice is the insert() function. However, + // it inserts the element only in case the element is not already contained in the pageslice. + pageslice0.insert( 50UL, 3.7 ); + + // A very efficient way to add new elements to a sparse pageslice is the append() function. + // Note that append() requires that the appended element's index is strictly larger than + // the currently largest non-zero index of the pageslice and that the pageslice's capacity is large + // enough to hold the new element. + pageslice0.reserve( 10UL ); + pageslice0.append( 51UL, -2.1 ); + \endcode + +// \n \section pageslice_common_operations Common Operations +// +// A pageslice view can be used like any other pageslice vector. For instance, the current number of pageslice +// elements can be obtained via the \c size() function, the current capacity via the \c capacity() +// function, and the number of non-zero elements via the \c nonZeros() function. However, since +// pageslices are references to specific pageslices of a tensor, several operations are not possible, such as +// resizing and swapping. The following example shows this by means of a dense pageslice view: + + \code + blaze::DynamicTensor A( 42UL, 42UL ); + // ... Resizing and initialization + + // Creating a reference to the 2nd pageslice of tensor A + auto pageslice2 = pageslice( A, 2UL ); + + pageslice2.size(); // Returns the number of elements in the pageslice + pageslice2.capacity(); // Returns the capacity of the pageslice + pageslice2.nonZeros(); // Returns the number of non-zero elements contained in the pageslice + + pageslice2.resize( 84UL ); // Compilation error: Cannot resize a single pageslice of a tensor + + auto pageslice3 = pageslice( A, 3UL ); + swap( pageslice2, pageslice3 ); // Compilation error: Swap operation not allowed + \endcode + +// \n \section pageslice_arithmetic_operations Arithmetic Operations +// +// Both dense and sparse pageslices can be used in all arithmetic operations that any other dense or +// sparse pageslice vector can be used in. The following example gives an impression of the use of +// dense pageslices within arithmetic operations. All operations (addition, subtraction, multiplication, +// scaling, ...) can be performed on all possible combinations of dense and sparse pageslices with +// fitting element types: + + \code + blaze::DynamicVector a( 2UL, 2.0 ), b; + blaze::CompressedVector c( 2UL ); + c[1] = 3.0; + + blaze::DynamicTensor A( 4UL, 2UL ); // Non-initialized 4x2 tensor + + auto pageslice0( pageslice( A, 0UL ) ); // Reference to the 0th pageslice of A + + pageslice0[0] = 0.0; // Manual initialization of the 0th pageslice of A + pageslice0[1] = 0.0; + pageslice( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st pageslice of A + pageslice( A, 2UL ) = a; // Dense vector initialization of the 2nd pageslice of A + pageslice( A, 3UL ) = c; // Sparse vector initialization of the 3rd pageslice of A + + b = pageslice0 + a; // Dense vector/dense vector addition + b = c + pageslice( A, 1UL ); // Sparse vector/dense vector addition + b = pageslice0 * pageslice( A, 2UL ); // Component-wise vector multiplication + + pageslice( A, 1UL ) *= 2.0; // In-place scaling of the 1st pageslice + b = pageslice( A, 1UL ) * 2.0; // Scaling of the 1st pageslice + b = 2.0 * pageslice( A, 1UL ); // Scaling of the 1st pageslice + + pageslice( A, 2UL ) += a; // Addition assignment + pageslice( A, 2UL ) -= c; // Subtraction assignment + pageslice( A, 2UL ) *= pageslice( A, 0UL ); // Multiplication assignment + + double scalar = pageslice( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors + + A = trans( c ) * pageslice( A, 1UL ); // Outer product between two vectors + \endcode + +// \n \section pageslice_on_column_major_tensor PageSlices on Column-Major Matrices +// +// Especially noteworthy is that pageslice views can be created for both pageslice-major and column-major +// matrices. Whereas the interface of a pageslice-major tensor only allows to traverse a pageslice directly +// and the interface of a column-major tensor only allows to traverse a column, via views it is +// possible to traverse a pageslice of a column-major tensor or a column of a pageslice-major tensor. For +// instance: + + \code + blaze::DynamicTensor A( 64UL, 32UL ); + // ... Resizing and initialization + + // Creating a reference to the 1st pageslice of a column-major tensor A + auto pageslice1 = pageslice( A, 1UL ); + + for( auto it=pageslice1.begin(); it!=pageslice1.end(); ++it ) { + // ... + } + \endcode + +// However, please note that creating a pageslice view on a tensor stored in a column-major fashion +// can result in a considerable performance decrease in comparison to a pageslice view on a tensor +// with pageslice-major storage format. This is due to the non-contiguous storage of the tensor +// elements. Therefore care has to be taken in the choice of the most suitable storage order: + + \code + // Setup of two column-major matrices + blaze::DynamicTensor A( 128UL, 128UL ); + blaze::DynamicTensor B( 128UL, 128UL ); + // ... Resizing and initialization + + // The computation of the 15th pageslice of the multiplication between A and B ... + blaze::DynamicVector x = pageslice( A * B, 15UL ); + + // ... is essentially the same as the following computation, which multiplies + // the 15th pageslice of the column-major tensor A with B. + blaze::DynamicVector x = pageslice( A, 15UL ) * B; + \endcode + +// Although Blaze performs the resulting vector/tensor multiplication as efficiently as possible +// using a pageslice-major storage order for tensor \c A would result in a more efficient evaluation. +*/ +//************************************************************************************************* + +#endif diff --git a/blaze_tensor/math/views/arrayslice/ArraySliceData.h b/blaze_tensor/math/views/arrayslice/ArraySliceData.h new file mode 100644 index 0000000..5d6ad16 --- /dev/null +++ b/blaze_tensor/math/views/arrayslice/ArraySliceData.h @@ -0,0 +1,251 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/views/arrayslice/ArraySliceData.h +// \brief Header file for the implementation of the ArraySliceData class template +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICEDATA_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICEDATA_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Auxiliary class template for the data members of the ArraySlice class. +// \ingroup arrayslice +// +// The auxiliary ArraySliceData class template represents an abstraction of the data members of the +// ArraySlice class template. The necessary set of data members is selected depending on the number +// of compile time arrayslice arguments. +*/ +template< size_t... CRAs > // Compile time arrayslice arguments +struct ArraySliceData +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR ZERO COMPILE TIME PAGESLICE INDICES +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the ArraySliceData class template for zero compile time arrayslice arguments. +// \ingroup arrayslice +// +// This specialization of ArraySliceData adapts the class template to the requirements of zero compile +// time arrayslice arguments. +*/ +template<> +struct ArraySliceData<> +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + template< typename... RRAs > + explicit inline ArraySliceData( size_t index, RRAs... args ); + + ArraySliceData( const ArraySliceData& ) = default; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~ArraySliceData() = default; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + ArraySliceData& operator=( const ArraySliceData& ) = delete; + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + inline size_t index() const noexcept; + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + const size_t arrayslice_; //!< The index of the arrayslice in the tensor. + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief The constructor for ArraySliceData. +// +// \param index The index of the arrayslice. +// \param args The optional arrayslice arguments. +*/ +template< typename... RRAs > // Optional arrayslice arguments +inline ArraySliceData<>::ArraySliceData( size_t index, RRAs... args ) + : arrayslice_( index ) // The index of the arrayslice in the tensor +{ + MAYBE_UNUSED( args... ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the index of the arrayslice of the underlying dense tensor. +// +// \return The index of the arrayslice. +*/ +inline size_t ArraySliceData<>::index() const noexcept +{ + return arrayslice_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR ONE COMPILE TIME PAGESLICE INDEX +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the ArraySliceData class template for a single compile time arrayslice argument. +// \ingroup arrayslice +// +// This specialization of ArraySliceData adapts the class template to the requirements of a single +// compile time arrayslice argument. +*/ +template< size_t Index > // Compile time arrayslice index +struct ArraySliceData +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + template< typename... RRAs > + explicit inline ArraySliceData( RRAs... args ); + + ArraySliceData( const ArraySliceData& ) = default; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~ArraySliceData() = default; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + ArraySliceData& operator=( const ArraySliceData& ) = delete; + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + static inline constexpr size_t index() noexcept; + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief The constructor for ArraySliceData. +// +// \param args The optional arrayslice arguments. +*/ +template< size_t Index > // Compile time arrayslice index +template< typename... RRAs > // Optional arrayslice arguments +inline ArraySliceData::ArraySliceData( RRAs... args ) +{ + MAYBE_UNUSED( args... ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the index of the arrayslice of the underlying dense tensor. +// +// \return The index of the arrayslice. +*/ +template< size_t Index > // Compile time arrayslice index +inline constexpr size_t ArraySliceData::index() noexcept +{ + return Index; +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/arrayslice/BaseTemplate.h b/blaze_tensor/math/views/arrayslice/BaseTemplate.h new file mode 100644 index 0000000..6769c64 --- /dev/null +++ b/blaze_tensor/math/views/arrayslice/BaseTemplate.h @@ -0,0 +1,123 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/views/arrayslice/BaseTemplate.h +// \brief Header file for the implementation of the ArraySlice base template +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_BASETEMPLATE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_BASETEMPLATE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include +// #include +#include +// #include +// #include +#include +#include +// #include +// #include +#include + + +namespace blaze { + +//================================================================================================= +// +// ::blaze NAMESPACE FORWARD DECLARATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Base template of the ArraySlice class template. +// \ingroup arrayslice +*/ +template< size_t M // Dimension of the slice + , typename MT // Type of the tensor + , size_t... CRAs > // Compile time arrayslice arguments +class ArraySlice; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ALIAS DECLARATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary alias declaration for the ArraySlice class template. +// \ingroup arrayslice +// +// The ArraySlice_ alias declaration represents a convenient shortcut for the specification of the +// non-derived template arguments of the ArraySlice class template. +*/ +template< size_t M // Dimension of the slice + , typename MT // Type of the tensor + , size_t... CRAs > // Compile time arrayslice arguments +using ArraySlice_ = ArraySlice< M, MT, CRAs... >; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/arrayslice/Dense.h b/blaze_tensor/math/views/arrayslice/Dense.h new file mode 100644 index 0000000..7178501 --- /dev/null +++ b/blaze_tensor/math/views/arrayslice/Dense.h @@ -0,0 +1,2129 @@ +//================================================================================================= +/*! +// \file blaze_array/math/views/arrayslice/Dense.h +// \brief ArraySlice specialization for dense arrays +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_DENSE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_DENSE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +// #include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR DENSE TENSORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of ArraySlice for arrayslices on arrayslice-major dense arrays. +// \ingroup arrayslice +// +// This specialization of ArraySlice adapts the class template to the requirements of arrayslice-major +// dense arrays. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +class ArraySlice + : public View< DenseArray< ArraySlice > > + , private ArraySliceData +{ + private: + //**Type definitions**************************************************************************** + using DataType = ArraySliceData; //!< The type of the ArraySliceData base class. + using Operand = If_t< IsExpression_v, MT, MT& >; //!< Composite data type of the dense array expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + //! Type of this ArraySlice instance. + using This = ArraySlice; + + using BaseType = DenseArray; //!< Base type of this ArraySlice instance. + using ViewedType = MT; //!< The type viewed by this ArraySlice instance. + using ResultType = ArraySliceTrait_t; //!< Result type for expression template evaluations. + using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Type of the arrayslice elements. + using SIMDType = SIMDTrait_t; //!< SIMD type of the arrayslice elements. + using ReturnType = ReturnType_t; //!< Return type for expression template evaluations + using CompositeType = const ArraySlice&; //!< Data type for composite expression templates. + + //! Reference to a constant arrayslice value. + using ConstReference = ConstReference_t; + + //! Reference to a non-constant arrayslice value. + using Reference = If_t< IsConst_v, ConstReference, Reference_t >; + + //! Pointer to a constant arrayslice value. + using ConstPointer = ConstPointer_t; + + //! Pointer to a non-constant arrayslice value. + using Pointer = If_t< IsConst_v || !HasMutableDataAccess_v, ConstPointer, Pointer_t >; + + //! Iterator over constant elements. + using ConstIterator = ConstIterator_t; + + //! Iterator over non-constant elements. + using Iterator = If_t< IsConst_v, ConstIterator, Iterator_t >; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = MT::simdEnabled; + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = MT::smpAssignable; + + //! Compile time dimensions of this array slice. + static constexpr size_t N = MT::num_dimensions() - 1; + //********************************************************************************************** + + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + template< typename... RRAs > + explicit inline ArraySlice( MT& array, RRAs... args ); + + ArraySlice( const ArraySlice& ) = default; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~ArraySlice() = default; + //@} + //********************************************************************************************** + + //**Data access functions*********************************************************************** + /*!\name Data access functions */ + //@{ + template< typename... Dims > + inline Reference operator()( Dims... dims ); + template< typename... Dims > + inline ConstReference operator()( Dims... dims ) const; + inline Reference operator()( std::array< size_t, N > const& indices ); + inline ConstReference operator()( std::array< size_t, N > const& indices ) const; + template< typename... Dims > + inline Reference at( Dims... dims ); + template< typename... Dims > + inline ConstReference at( Dims... dims ) const; + inline Pointer data () noexcept; + inline ConstPointer data () const noexcept; + inline Pointer data ( size_t i ) noexcept; + inline ConstPointer data ( size_t i ) const noexcept; + inline Iterator begin ( size_t i ); + inline ConstIterator begin ( size_t i ) const; + inline ConstIterator cbegin( size_t i ) const; + inline Iterator end ( size_t i ); + inline ConstIterator end ( size_t i ) const; + inline ConstIterator cend ( size_t i ) const; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + inline ArraySlice& operator=( const ElementType& rhs ); + inline ArraySlice& operator=( nested_initializer_list list ); + inline ArraySlice& operator=( const ArraySlice& rhs ); + + template< typename MT2 > inline ArraySlice& operator= ( const Array& rhs ); + template< typename MT2 > inline ArraySlice& operator+=( const Array& rhs ); + template< typename MT2 > inline ArraySlice& operator-=( const Array& rhs ); + template< typename MT2 > inline ArraySlice& operator%=( const Array& rhs ); + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + using DataType::index; + + inline MT& operand() noexcept; + inline const MT& operand() const noexcept; + + inline size_t rows() const noexcept; + inline size_t columns() const noexcept; + inline size_t spacing() const noexcept; + inline size_t capacity() const noexcept; + inline size_t capacity( size_t i ) const noexcept; + inline size_t nonZeros() const; + inline size_t nonZeros( size_t i ) const; + inline void reset(); + inline void reset( size_t i ); + //@} + //********************************************************************************************** + + //**Numeric functions*************************************************************************** + /*!\name Numeric functions */ + //@{ + template< typename Other > inline ArraySlice& scale( const Other& scalar ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool VectorizedAssign_v = + ( useOptimizedKernels && + simdEnabled && MT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool VectorizedAddAssign_v = + ( useOptimizedKernels && + simdEnabled && MT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > && + HasSIMDAdd_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool VectorizedSubAssign_v = + ( useOptimizedKernels && + simdEnabled && MT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > && + HasSIMDSub_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT2 > + static constexpr bool VectorizedSchurAssign_v = + ( useOptimizedKernels && + simdEnabled && MT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > && + HasSIMDMult_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + public: + //**Expression template evaluation functions**************************************************** + /*!\name Expression template evaluation functions */ + //@{ + template< typename Other > + inline bool canAlias( const Other* alias ) const noexcept; + + template< size_t M2, typename MT2, size_t... CRAs2 > + inline bool canAlias( const ArraySlice* alias ) const noexcept; + + template< typename Other > + inline bool isAliased( const Other* alias ) const noexcept; + + template< size_t M2, typename MT2, size_t... CRAs2 > + inline bool isAliased( const ArraySlice* alias ) const noexcept; + + inline bool isAligned () const noexcept; + inline bool canSMPAssign() const noexcept; + + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType load ( Dims... dims ) const noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType loada( Dims... dims ) const noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType loadu( Dims... dims ) const noexcept; + + template< typename... Dims > + BLAZE_ALWAYS_INLINE void store ( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void storea( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void storeu( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void stream( const SIMDType& value, Dims... dims ) noexcept; + + template< typename MT2 > + inline auto assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v >; + + template< typename MT2 > + inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; + + template< typename MT2 > + inline auto addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; + + template< typename MT2 > + inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; + + template< typename MT2 > + inline auto subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; + + template< typename MT2 > + inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; + + template< typename MT2 > + inline auto schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; + + template< typename MT2 > + inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + Operand array_; //!< The array containing the arrayslice. + //@} + //********************************************************************************************** + + //**Friend declarations************************************************************************* + template< size_t M2, typename MT2, size_t... CRAs2 > friend class ArraySlice; + //********************************************************************************************** + + //**Compile time checks************************************************************************* + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( MT ); + BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT ); + BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT ); +// BLAZE_CONSTRAINT_MUST_NOT_BE_SUBARRAY_TYPE ( MT ); + BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT ); + BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Constructor for arrayslices on arrayslice-major dense arrays. +// +// \param array The array containing the arrayslice. +// \param args The runtime arrayslice arguments. +// \exception std::invalid_argument Invalid arrayslice access index. +// +// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly +// specified (i.e. if the specified index is greater than the number of pages of the given array) +// a \a std::invalid_argument exception is thrown. The checks can be skipped by providing the +// optional \a blaze::unchecked argument. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... RRAs > // Runtime arrayslice arguments +inline ArraySlice::ArraySlice( MT& array, RRAs... args ) + : DataType( args... ) // Base class initialization + , array_ ( array ) // The array containing the arrayslice +{ + if( !Contains_v< TypeList, Unchecked > ) { + if( array_.template dimension() <= index() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid arrayslice access index" ); + } + } + else { + BLAZE_USER_ASSERT( index() < array_..template dimension(), "Invalid arrayslice access index" ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DATA ACCESS FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subscript operator for the direct access to the arrayslice elements. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access index. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +inline typename ArraySlice::Reference + ArraySlice::operator()( Dims... dims ) +{ + BLAZE_STATIC_ASSERT( M < sizeof...(Dims) ); + + return array_( fused_indices< M >( index(), dims... ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subscript operator for the direct access to the arrayslice elements. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access index. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +inline typename ArraySlice::ConstReference + ArraySlice::operator()( Dims... dims ) const +{ + BLAZE_STATIC_ASSERT( M < sizeof...(Dims) ); + + return const_cast< const MT& >( array_ )( fused_indices< M >( index(), dims... ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subscript operator for the direct access to the arrayslice elements. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access index. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::Reference + ArraySlice::operator()( std::array< size_t, N > const& indices ) +{ + BLAZE_STATIC_ASSERT( M < N ); + + return array_( fused_indices< M >( index(), indices ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subscript operator for the direct access to the arrayslice elements. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access index. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstReference + ArraySlice::operator()( std::array< size_t, N > const& indices ) const +{ + BLAZE_STATIC_ASSERT( M < N ); + + return const_cast< const MT& >( array_ )( fused_indices< M >( index(), indices ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Checked access to the arrayslice elements. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid arrayslice access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access index. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +inline typename ArraySlice::Reference + ArraySlice::at( Dims... dims ) +{ + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dimensions(), [&]( size_t i ) { + if( indices[N - i - 1] >= dimensions()[i] ) { + BLAZE_THROW_OUT_OF_RANGE("Invalid array access index"); + } + } ); + + return ( *this )( dims... ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Checked access to the arrayslice elements. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid arrayslice access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access index. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +inline typename ArraySlice::ConstReference + ArraySlice::at( Dims... dims) const +{ + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dimensions(), [&]( size_t i ) { + if( indices[N - i - 1] >= dimensions()[i] ) { + BLAZE_THROW_OUT_OF_RANGE("Invalid array access index"); + } + } ); + + return ( *this )( dims... ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the arrayslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case +// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::Pointer + ArraySlice::data() noexcept +{ + return nullptr; //array_.data( fused_indices( index(), 0, 0 ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the arrayslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case +// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstPointer + ArraySlice::data() const noexcept +{ + return nullptr; //array_.data( 0, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the arrayslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case +// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::Pointer + ArraySlice::data( size_t i ) noexcept +{ + return nullptr; // array_.data( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the arrayslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case +// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstPointer + ArraySlice::data( size_t i ) const noexcept +{ + return nullptr; // array_.data( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator to the first element of the arrayslice. +// +// \param i The row/column index. +// \return Iterator to the first element of the given row on this arrayslice. +// +// This function returns an iterator to the first element of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::Iterator + ArraySlice::begin( size_t i ) +{ + return array_.begin( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator to the first element of the arrayslice. +// +// \param i The row/column index. +// \return Iterator to the first element of the arrayslice. +// +// This function returns an iterator to the first element of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstIterator + ArraySlice::begin( size_t i ) const +{ + return array_.cbegin( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator to the first element of the arrayslice. +// +// \param i The row/column index. +// \return Iterator to the first element of the arrayslice. +// +// This function returns an iterator to the first element of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstIterator + ArraySlice::cbegin( size_t i ) const +{ + return array_.cbegin( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator just past the last element of the arrayslice. +// +// \param i The row/column index. +// \return Iterator just past the last element of the arrayslice. +// +// This function returns an iterator just past the last element of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::Iterator + ArraySlice::end( size_t i ) +{ + return array_.end( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator just past the last element of the arrayslice. +// +// \param i The row/column index. +// \return Iterator just past the last element of the arrayslice. +// +// This function returns an iterator just past the last element of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstIterator + ArraySlice::end( size_t i ) const +{ + return array_.cend( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator just past the last element of the arrayslice. +// +// \param i The row/column index. +// \return Iterator just past the last element of the arrayslice. +// +// This function returns an iterator just past the last element of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline typename ArraySlice::ConstIterator + ArraySlice::cend( size_t i ) const +{ + return array_.cend( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ASSIGNMENT OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Homogeneous assignment to all arrayslice elements. +// +// \param rhs Scalar value to be assigned to all arrayslice elements. +// \return Reference to the assigned arrayslice. +// +// This function homogeneously assigns the given value to all elements of the arrayslice. Note that in +// case the underlying dense array is a lower/upper array only lower/upper and diagonal elements +// of the underlying array are modified. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline ArraySlice& + ArraySlice::operator=( const ElementType& rhs ) +{ + decltype(auto) left( derestrict( array_ ) ); + + for (size_t i=0UL; i || trySet(*this, i, j, rhs)) + { + left(page(), i, j) = rhs; + } + } + } + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief List assignment to all arrayslice elements. +// +// \param list The initializer list. +// \exception std::invalid_argument Invalid assignment to arrayslice. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// This assignment operator offers the option to directly assign to all elements of the dense +// arrayslice by means of an initializer list. The arrayslice elements are assigned the values from the given +// initializer list. Missing values are reset to their default state. Note that in case the size +// of the initializer list exceeds the size of the arrayslice, a \a std::invalid_argument exception is +// thrown. Also, if the underlying array \a MT is restricted and the assignment would violate +// an invariant of the array, a \a std::invalid_argument exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline ArraySlice& + ArraySlice::operator=(nested_initializer_list list) +{ + if (list.size() > rows() || determineColumns(list) > columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to arrayslice" ); + } + + if( IsRestricted_v ) { + const InitializerArray tmp( list ); + if( !tryAssign( array_, tmp, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + } + + decltype(auto) left( derestrict( *this ) ); + + size_t i( 0UL ); + + for( const auto& rowList : list ) { + std::fill( std::copy( rowList.begin(), rowList.end(), left.begin( i ) ), left.end( i ), ElementType() ); + ++i; + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Copy assignment operator for ArraySlice. +// +// \param rhs Dense arrayslice to be copied. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument ArraySlice sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two arrayslices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline ArraySlice& + ArraySlice::operator=( const ArraySlice& rhs ) +{ + if( &rhs == this ) return *this; + + if( rows() != rhs.rows() || columns() != rhs.columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "ArraySlice sizes do not match" ); + } + + if( !tryAssign( array_, rhs, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsExpression_v && rhs.canAlias( &array_ ) ) { + const ResultType tmp( rhs ); + smpAssign( left, tmp ); + } + else { + smpAssign( left, rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Assignment operator for different matrices. +// +// \param rhs Array to be assigned. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Array sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side matrix +inline ArraySlice& + ArraySlice::operator=( const Array& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; + Right right( ~rhs ); + + if( !tryAssign( array_, right, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &array_ ) ) { + const ResultType_t tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseArray_v ) + reset(); + smpAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Addition assignment operator for the addition of a matrix (\f$ \vec{a}+=\vec{b} \f$). +// +// \param rhs The right-hand side matrix to be added to the dense arrayslice. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Vector sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side matrix +inline ArraySlice& + ArraySlice::operator+=( const Array& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; + Right right( ~rhs ); + + if( !tryAddAssign( array_, right, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &array_ ) ) { + const ResultType_t tmp( right ); + smpAddAssign( left, tmp ); + } + else { + smpAddAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ \vec{a}-=\vec{b} \f$). +// +// \param rhs The right-hand side matrix to be subtracted from the dense arrayslice. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Vector sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side matrix +inline ArraySlice& + ArraySlice::operator-=( const Array& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; + Right right( ~rhs ); + + if( !trySubAssign( array_, right, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &array_ ) ) { + const ResultType_t tmp( right ); + smpSubAssign( left, tmp ); + } + else { + smpSubAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Schur product assignment operator for the multiplication of a matrix +// (\f$ \vec{a}\times=\vec{b} \f$). +// +// \param rhs The right-hand side matrix for the cross product. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Invalid matrix size for cross product. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current size of any of the two matrices is not equal to 3, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side matrix +inline ArraySlice& + ArraySlice::operator%=( const Array& rhs ) +{ + using blaze::assign; + + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + using SchurType = SchurTrait_t< ResultType, ResultType_t >; + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( !trySchurAssign( array_, (~rhs), 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && (~rhs).canAlias( &array_ ) ) { + const SchurType tmp( *this % (~rhs) ); + smpSchurAssign( left, tmp ); + } + else { + smpSchurAssign( left, ~rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the array containing the arrayslice. +// +// \return The array containing the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline MT& ArraySlice::operand() noexcept +{ + return array_; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the array containing the arrayslice. +// +// \return The array containing the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline const MT& ArraySlice::operand() const noexcept +{ + return array_; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the current size/dimension of the arrayslice. +// +// \return The size of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::rows() const noexcept +{ + return array_.rows(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the current size/dimension of the arrayslice. +// +// \return The size of the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::columns() const noexcept +{ + return array_.columns(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the minimum capacity of the arrayslice. +// +// \return The minimum capacity of the arrayslice. +// +// This function returns the minimum capacity of the arrayslice, which corresponds to the current size +// plus padding. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::spacing() const noexcept +{ + return array_.spacing(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the maximum capacity of the dense arrayslice. +// +// \return The maximum capacity of the dense arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::capacity() const noexcept +{ + return array_.capacity( 0UL, page() ) * array_.rows(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the maximum capacity of the dense arrayslice. +// +// \return The maximum capacity of the dense arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::capacity( size_t i ) const noexcept +{ + return array_.capacity( i, page() ) * array_.rows(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the number of non-zero elements in the arrayslice. +// +// \return The number of non-zero elements in the arrayslice. +// +// Note that the number of non-zero elements is always less than or equal to the current number +// of columns of the array containing the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::nonZeros() const +{ + size_t count ( 0 ); + for ( size_t i = 0; i < rows(); ++i ) { + count += array_.nonZeros( i, page() ); + } + return count; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the number of non-zero elements in the arrayslice. +// +// \return The number of non-zero elements in the arrayslice. +// +// Note that the number of non-zero elements is always less than or equal to the current number +// of columns of the array containing the arrayslice. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline size_t ArraySlice::nonZeros( size_t i ) const +{ + return array_.nonZeros( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Reset to the default initial values. +// +// \return void +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline void ArraySlice::reset() +{ + for ( size_t i = 0; i < rows(); ++i ) { + array_.reset( i, page() ); + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Reset to the default initial values. +// +// \return void +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline void ArraySlice::reset( size_t i ) +{ + array_.reset( i, page() ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// NUMERIC FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Scaling of the arrayslice by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$). +// +// \param scalar The scalar value for the arrayslice scaling. +// \return Reference to the dense arrayslice. +// +// This function scales the arrayslice by applying the given scalar value \a scalar to each element +// of the arrayslice. For built-in and \c complex data types it has the same effect as using the +// multiplication assignment operator. Note that the function cannot be used to scale a arrayslice +// on a lower or upper unitriangular array. The attempt to scale such a arrayslice results in a +// compile time error! +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename Other > // Data type of the scalar value +inline ArraySlice& + ArraySlice::scale( const Other& scalar ) +{ + for ( size_t i = 0; i < rows(); ++i ) { + for ( size_t j = 0; j < columns(); ++j ) { + array_(page(), i, j) *= scalar; + } + } + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TEMPLATE EVALUATION FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense arrayslice can alias with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. +// +// This function returns whether the given address can alias with the dense arrayslice. In contrast +// to the isAliased() function this function is allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename Other > // Data type of the foreign expression +inline bool ArraySlice::canAlias( const Other* alias ) const noexcept +{ + return array_.isAliased( alias ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense arrayslice can alias with the given dense arrayslice \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. +// +// This function returns whether the given address can alias with the dense arrayslice. In contrast +// to the isAliased() function this function is allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< size_t M2 // Dimension of the ArraysSlice + , typename MT2 // Data type of the foreign dense arrayslice + , size_t... CRAs2 > // Compile time arrayslice arguments of the foreign dense arrayslice +inline bool + ArraySlice::canAlias( const ArraySlice* alias ) const noexcept +{ + return array_.isAliased( &alias->array_ ) && ( page() == alias->page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense arrayslice is aliased with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. +// +// This function returns whether the given address is aliased with the dense arrayslice. In contrast +// to the canAlias() function this function is not allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename Other > // Data type of the foreign expression +inline bool ArraySlice::isAliased( const Other* alias ) const noexcept +{ + return array_.isAliased( alias ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense arrayslice is aliased with the given dense arrayslice \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. +// +// This function returns whether the given address is aliased with the dense arrayslice. In contrast +// to the canAlias() function this function is not allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< size_t M2 // Dimension of the ArraysSlice + , typename MT2 // Data type of the foreign dense arrayslice + , size_t... CRAs2 > // Compile time arrayslice arguments of the foreign dense arrayslice +inline bool + ArraySlice::isAliased( const ArraySlice* alias ) const noexcept +{ + return array_.isAliased( &alias->array_ ) && ( page() == alias->page() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense arrayslice is properly aligned in memory. +// +// \return \a true in case the dense arrayslice is aligned, \a false if not. +// +// This function returns whether the dense arrayslice is guaranteed to be properly aligned in memory, +// i.e. whether the beginning and the end of the dense arrayslice are guaranteed to conform to the +// alignment restrictions of the element type \a Type. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline bool ArraySlice::isAligned() const noexcept +{ + return array_.isAligned(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense arrayslice can be used in SMP assignments. +// +// \return \a true in case the dense arrayslice can be used in SMP assignments, \a false if not. +// +// This function returns whether the dense arrayslice can be used in SMP assignments. In contrast to +// the \a smpAssignable member enumeration, which is based solely on compile time information, +// this function additionally provides runtime information (as for instance the current size +// of the dense arrayslice). +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +inline bool ArraySlice::canSMPAssign() const noexcept +{ + return ( rows() * columns() > SMP_DMATASSIGN_THRESHOLD ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Load of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return The loaded SIMD element. +// +// This function performs a load of a specific SIMD element of the dense arrayslice. The index +// must be smaller than the number of array columns. This function must \b NOT be called +// explicitly! It is used internally for the performance optimized evaluation of expression +// templates. Calling this function explicitly might result in erroneous results and/or in +// compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename ArraySlice::SIMDType + ArraySlice::load( Dims... dims ) const noexcept +{ + return array_.load( page(), i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Aligned load of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return The loaded SIMD element. +// +// This function performs an aligned load of a specific SIMD element of the dense arrayslice. +// The index must be smaller than the number of array columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename ArraySlice::SIMDType + ArraySlice::loada( Dims... dims ) const noexcept +{ + return array_.loada( page(), i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Unaligned load of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \return The loaded SIMD element. +// +// This function performs an unaligned load of a specific SIMD element of the dense arrayslice. +// The index must be smaller than the number of array columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename ArraySlice::SIMDType + ArraySlice::loadu( Dims... dims ) const noexcept +{ + return array_.loadu( page(), i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Store of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs a store a specific SIMD element of the dense arrayslice. The index +// must be smaller than the number of array columns. This function must \b NOT be called +// explicitly! It is used internally for the performance optimized evaluation of expression +// templates. Calling this function explicitly might result in erroneous results and/or in +// compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + ArraySlice::store( const SIMDType& value, Dims... dims ) noexcept +{ + array_.store( page(), i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Aligned store of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned store a specific SIMD element of the dense arrayslice. The +// index must be smaller than the number of array columns. This function must \b NOT be +// called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + ArraySlice::storea( const SIMDType& value, Dims... dims ) noexcept +{ + array_.storea( page(), i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Unligned store of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an unaligned store a specific SIMD element of the dense arrayslice. +// The index must be smaller than the number of array columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + ArraySlice::storeu( const SIMDType& value, Dims... dims ) noexcept +{ + array_.storeu( page(), i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Aligned, non-temporal store of a SIMD element of the dense arrayslice. +// +// \param index Access index. The index must be smaller than the number of array columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned, non-temporal store a specific SIMD element of the dense +// arrayslice. The index must be smaller than the number of array columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + ArraySlice::stream( const SIMDType& value, Dims... dims ) noexcept +{ + array_.stream( page(), i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::assign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedAssign_v > +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows(), "Invalid matrix sizes" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid matrix sizes" ); + + for (size_t i = 0UL; i < (~rhs).rows(); ++i ) { + const size_t jpos( (~rhs).columns() & size_t(-2) ); + for( size_t j=0UL; j // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::assign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for (size_t i = 0; i < (~rhs).rows(); ++i) { + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); + BLAZE_INTERNAL_ASSERT( !remainder || ( cols - ( cols % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); + + size_t j( 0UL ); + Iterator left( begin(i) ); + ConstIterator_t right( (~rhs).begin(i) ); + + if( useStreaming && cols > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &array_ ) ) + { + for( ; j // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::addAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedAddAssign_v > +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + for (size_t i = 0UL; i < (~rhs).rows(); ++i ) { + const size_t jpos( (~rhs).columns() & size_t(-2) ); + for( size_t j=0UL; j // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::addAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedAddAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for (size_t i = 0; i < (~rhs).rows(); ++i) { + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); + BLAZE_INTERNAL_ASSERT( !remainder || ( cols - ( cols % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); + + size_t j( 0UL ); + Iterator left( begin(i) ); + ConstIterator_t right( (~rhs).begin(i) ); + + for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) { + left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; + } + for( ; j // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::subAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedSubAssign_v > +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + for (size_t i = 0UL; i < (~rhs).rows(); ++i ) { + const size_t jpos( (~rhs).columns() & size_t(-2) ); + for( size_t j=0UL; j // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::subAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedSubAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for (size_t i = 0; i < (~rhs).rows(); ++i) { + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); + BLAZE_INTERNAL_ASSERT( !remainder || ( cols - ( cols % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); + + size_t j( 0UL ); + Iterator left( begin(i) ); + ConstIterator_t right( (~rhs).begin(i) ); + + for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) { + left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; + } + for( ; j // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::schurAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + const size_t jpos( columns() & size_t(-2) ); + BLAZE_INTERNAL_ASSERT( ( columns() - ( columns() % 2UL ) ) == jpos, "Invalid end calculation" ); + + for( size_t i=0UL; i // Compile time arrayslice arguments +template< typename MT2 > // Type of the right-hand side dense matrix +inline auto ArraySlice::schurAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for( size_t i=0UL; i right( (~rhs).begin(i) ); + + for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) { + left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; + left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; + } + for( ; j #include +#include namespace blaze { template< size_t Shift = 1, size_t N > -std::array< size_t, N - Shift > ArrayShift( std::array< size_t, N > const& dims ) +std::array< size_t, N - Shift > shiftDims( std::array< size_t, N > const& dims ) { BLAZE_STATIC_ASSERT(N >= 2 && N > Shift); // cannot shift more than elements @@ -55,6 +56,26 @@ std::array< size_t, N - Shift > ArrayShift( std::array< size_t, N > const& dims return result; } +template< size_t M, size_t N > +std::array< size_t, N + 1 > mergeDims( std::array< size_t, N > const& dims, size_t index ) +{ + BLAZE_STATIC_ASSERT( M <= N ); + + std::array< size_t, N + 1 > result; + + for( size_t i = 0; i != M; ++i ) { + result[i] = dims[i]; + } + + result[M] = index; + + for( size_t i = M + 1; i != N; ++i ) { + result[i] = dims[i - 1]; + } + + return result; +} + //************************************************************************************************* /*!\brief ArrayForEach function to iterate over arbitrary dimension data. // \ingroup util @@ -95,7 +116,7 @@ void ArrayForEach( std::array< size_t, N > const& dims, F const& f, size_t base = 0 ) { BLAZE_STATIC_ASSERT( N >= 2 ); - std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j) { ArrayForEach( shifted_dims, f, i ); } @@ -141,7 +162,7 @@ template< size_t N, typename F > void ArrayForEachPadded( std::array< size_t, 2 > const& dims, size_t nn, F const& f, size_t base = 0 ) { - std::array< size_t, 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, 1 > shifted_dims = shiftDims( dims ); for( size_t i = base * nn, j = 0; j != dims[1]; i += nn, ++j ) { ArrayForEachPadded( shifted_dims, nn, f, i ); } @@ -152,7 +173,7 @@ void ArrayForEachPadded( std::array< size_t, N > const& dims, size_t nn, F const& f, size_t base = 0 ) { BLAZE_STATIC_ASSERT( N >= 2 ); - std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j ) { ArrayForEachPadded( shifted_dims, nn, f, i ); } @@ -186,7 +207,7 @@ void ArrayForEachGrouped( std::array< size_t, N > const& dims, F const& f, std::array< size_t, M >& currdims ) { BLAZE_STATIC_ASSERT( N > 2 ); - std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); for( currdims[N - 1] = 0; currdims[N - 1] != dims[N - 1]; ++currdims[N - 1] ) { ArrayForEachGrouped( shifted_dims, f, currdims ); } @@ -218,7 +239,7 @@ template< typename F, size_t M > void ArrayForEachGrouped( std::array< size_t, 2 > const& dims, size_t nn, F const& f, std::array< size_t, M >& currdims, size_t base = 0 ) { - std::array< size_t, 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, 1 > shifted_dims = shiftDims( dims ); currdims[1] = 0; for( size_t i = base * nn; currdims[1] != dims[1]; i += nn, ++currdims[1]) { ArrayForEachGrouped( dims[0], f, currdims, i ); @@ -230,7 +251,7 @@ void ArrayForEachGrouped( std::array< size_t, N > const& dims, size_t nn, F const& f, std::array< size_t, M >& currdims, size_t base = 0 ) { BLAZE_STATIC_ASSERT( N > 2 ); - std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); currdims[N - 1] = 0; for( size_t i = base * dims[N - 2]; currdims[N - 1] != dims[N - 1]; i += dims[N - 2], ++currdims[N - 1]) { ArrayForEachGrouped( shifted_dims, nn, f, currdims, i ); @@ -297,7 +318,7 @@ void ArrayForEach2( std::array< size_t, N > const& dims, size_t nn, F const& f, size_t base = 0 ) { BLAZE_STATIC_ASSERT( N > 2 ); - std::array< size_t, N - 1 > shifted_dims = ArrayShift( dims ); + std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j ) { ArrayForEach2( shifted_dims, nn, f, i ); } @@ -326,7 +347,7 @@ bool ArrayForEachGroupedAnyOf( std::array< size_t, N > const& dims, F const& f, { while( currdims[N - 1] != dims[N - 1] ) { currdims[N - 2] = 0; - if( ArrayForEachGroupedAnyOf( ArrayShift( dims ), f, currdims ) ) { + if( ArrayForEachGroupedAnyOf( shiftDims( dims ), f, currdims ) ) { return true; } ++currdims[N - 1]; @@ -367,7 +388,7 @@ bool ArrayForEachGroupedAllOf( std::array< size_t, N > const& dims, F const& f, { while( currdims[N - 1] != dims[N - 1] ) { currdims[N - 2] = 0; - if( !ArrayForEachGroupedAllOf( ArrayShift( dims ), f, currdims ) ) { + if( !ArrayForEachGroupedAllOf( shiftDims( dims ), f, currdims ) ) { return false; } ++currdims[N - 1]; diff --git a/blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h b/blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h new file mode 100644 index 0000000..f15e15b --- /dev/null +++ b/blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h @@ -0,0 +1,432 @@ +//================================================================================================= +/*! +// \file blazetest/mathtest/arrayslice/DenseGeneralTest.h +// \brief Header file for the ArraySlice dense general test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZETEST_MATHTEST_ARRAYSLICE_DENSEGENERALTEST_H_ +#define _BLAZETEST_MATHTEST_ARRAYSLICE_DENSEGENERALTEST_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + +#include +#include +#include + +namespace blazetest { + +namespace mathtest { + +namespace arrayslice { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Auxiliary class for all tests of the dense general ArraySlice specialization. +// +// This class represents a test suite for the blaze::ArraySlice class template specialization for +// dense general matrices. It performs a series of both compile time as well as runtime tests. +*/ +class DenseGeneralTest +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit DenseGeneralTest(); + // No explicitly declared copy constructor. + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + // No explicitly declared destructor. + //********************************************************************************************** + + private: + //**Test functions****************************************************************************** + /*!\name Test functions */ + //@{ + void testConstructors(); + void testAssignment(); + void testAddAssign(); + void testSubAssign(); + void testMultAssign(); + void testSchurAssign(); + void testScaling(); + void testFunctionCall(); + void testAt(); + void testIterator(); + void testNonZeros(); + void testReset(); + void testClear(); + void testIsDefault(); + void testIsSame(); + void testSubmatrix(); + void testRow(); + void testRows(); + void testColumn(); + void testColumns(); + void testBand(); + + template< typename Type > + void checkSize( const Type& arrayslice, size_t expectedSize ) const; + + template< typename Type > + void checkRows( const Type& array, size_t expectedRows ) const; + + template< typename Type > + void checkColumns( const Type& array, size_t expectedColumns ) const; + + template< typename Type > + void checkPages( const Type& array, size_t expectedPages ) const; + + template< typename Type > + void checkCapacity( const Type& object, size_t minCapacity ) const; + + template< typename Type > + void checkNonZeros( const Type& object, size_t expectedNonZeros ) const; + + template< typename Type > + void checkNonZeros( const Type& array, size_t i, size_t k, size_t expectedNonZeros ) const; + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + void initialize(); + //@} + //********************************************************************************************** + + //**Type definitions**************************************************************************** + using MT = blaze::DynamicArray<3, int>; //!< Dynamic array type. + using RT = blaze::ArraySlice<2, MT>; //!< Dense arrayslice type for arrays (slice along largest dimension). + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + MT mat_; //!< dynamic array. + std::string test_; //!< Label of the currently performed test. + //@} + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( MT ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( RT ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Checking the size of the given dense arrayslice. +// +// \param arrayslice The dense arrayslice to be checked. +// \param expectedSize The expected size of the dense arrayslice. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the size of the given dense arrayslice. In case the actual size does not +// correspond to the given expected size, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense arrayslice +void DenseGeneralTest::checkSize( const Type& arrayslice, size_t expectedSize ) const +{ + if( size( arrayslice ) != expectedSize ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid size detected\n" + << " Details:\n" + << " Size : " << size( arrayslice ) << "\n" + << " Expected size: " << expectedSize << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of arrayslices of the given dynamic array. +// +// \param array The dynamic array to be checked. +// \param expectedArraySlices The expected number of rows of the dynamic array. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of rows of the given dynamic array. In case the actual number +// of arrayslices does not correspond to the given expected number of arrayslices, a \a std::runtime_error +// exception is thrown. +*/ +template< typename Type > // Type of the dynamic array +void DenseGeneralTest::checkRows( const Type& array, size_t expectedRows ) const +{ + if( rows( array ) != expectedRows ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of rows detected\n" + << " Details:\n" + << " Number of rows : " << rows( array ) << "\n" + << " Expected number of rows: " << expectedRows << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of columns of the given dynamic array. +// +// \param array The dynamic array to be checked. +// \param expectedColumns The expected number of columns of the dynamic array. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of columns of the given dynamic array. In case the +// actual number of columns does not correspond to the given expected number of columns, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic array +void DenseGeneralTest::checkColumns( const Type& array, size_t expectedColumns ) const +{ + if( columns( array ) != expectedColumns ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of columns detected\n" + << " Details:\n" + << " Number of columns : " << columns( array ) << "\n" + << " Expected number of columns: " << expectedColumns << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of pages of the given dynamic array. +// +// \param array The dynamic array to be checked. +// \param expectedPages The expected number of columns of the dynamic array. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of pages of the given dynamic array. In case the +// actual number of pages does not correspond to the given expected number of pages, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic array +void DenseGeneralTest::checkPages( const Type& array, size_t expectedPages ) const +{ + if( pages( array ) != expectedPages ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of pages detected\n" + << " Details:\n" + << " Number of pages : " << pages( array ) << "\n" + << " Expected number of pages: " << expectedPages << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the capacity of the given dense arrayslice or dynamic array. +// +// \param object The dense arrayslice or dynamic array to be checked. +// \param minCapacity The expected minimum capacity. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the capacity of the given dense arrayslice or dynamic array. In case the actual +// capacity is smaller than the given expected minimum capacity, a \a std::runtime_error exception +// is thrown. +*/ +template< typename Type > // Type of the dense arrayslice or dynamic array +void DenseGeneralTest::checkCapacity( const Type& object, size_t minCapacity ) const +{ + if( capacity( object ) < minCapacity ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Capacity : " << capacity( object ) << "\n" + << " Expected minimum capacity: " << minCapacity << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements of the given dense arrayslice or dynamic array. +// +// \param object The dense arrayslice or dynamic array to be checked. +// \param expectedNonZeros The expected number of non-zero elements. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements of the given dense arrayslice. In case the +// actual number of non-zero elements does not correspond to the given expected number, a +// \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense arrayslice or dynamic array +void DenseGeneralTest::checkNonZeros( const Type& object, size_t expectedNonZeros ) const +{ + if( nonZeros( object ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements\n" + << " Details:\n" + << " Number of non-zeros : " << nonZeros( object ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( capacity( object ) < nonZeros( object ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( object ) << "\n" + << " Capacity : " << capacity( object ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements in a specific arrayslice/column of the given dynamic array. +// +// \param array The dynamic array to be checked. +// \param index The arrayslice/column to be checked. +// \param expectedNonZeros The expected number of non-zero elements in the specified arrayslice/column. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements in the specified arrayslice/column of the +// given dynamic array. In case the actual number of non-zero elements does not correspond +// to the given expected number, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic array +void DenseGeneralTest::checkNonZeros( const Type& array, size_t i, size_t k, size_t expectedNonZeros ) const +{ + if( nonZeros( array, i, k ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements in row " << i << " page " << k << "\n" + << " Details:\n" + << " Number of non-zeros : " << nonZeros( array, i, k ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( capacity( array, i, k ) < nonZeros( array, i, k ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected in row " << i << " page " << k << "\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( array, i, k ) << "\n" + << " Capacity : " << capacity( array, i, k ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Testing the functionality of the dense general ArraySlice specialization. +// +// \return void +*/ +void runTest() +{ + DenseGeneralTest(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// MACRO DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Macro for the execution of the ArraySlice dense general test. +*/ +#define RUN_ARRAYSLICE_DENSEGENERAL_TEST \ + blazetest::mathtest::arrayslice::runTest() +/*! \endcond */ +//************************************************************************************************* + +} // namespace arrayslice + +} // namespace mathtest + +} // namespace blazetest + +#endif diff --git a/blazetest/src/mathtest/CMakeLists.txt b/blazetest/src/mathtest/CMakeLists.txt index f1a1d68..9101660 100644 --- a/blazetest/src/mathtest/CMakeLists.txt +++ b/blazetest/src/mathtest/CMakeLists.txt @@ -31,6 +31,7 @@ # ================================================================================================= set(subdirs + arrayslice columnslice customtensor densearray diff --git a/blazetest/src/mathtest/arrayslice/CMakeLists.txt b/blazetest/src/mathtest/arrayslice/CMakeLists.txt new file mode 100644 index 0000000..6d5f612 --- /dev/null +++ b/blazetest/src/mathtest/arrayslice/CMakeLists.txt @@ -0,0 +1,44 @@ +# ================================================================================================= +# +# Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +# Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +# +# This file is part of the Blaze library. You can redistribute it and/or modify it under +# the terms of the New (Revised) BSD License. Redistribution and use in source and binary +# forms, with or without modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# 3. Neither the names of the Blaze development group nor the names of its contributors +# may be used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# ================================================================================================= + +set(category ArraySlice) + +set(tests + DenseGeneralTest + IncludeTest +) + +foreach(test ${tests}) + add_blaze_tensor_test(${category}${test} + SOURCES ${test}.cpp + FOLDER "Tests/${category}") +endforeach() diff --git a/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp new file mode 100644 index 0000000..8c34c14 --- /dev/null +++ b/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp @@ -0,0 +1,5157 @@ +//================================================================================================= +/*! +// \file src/mathtest/arrayslice/DenseGeneralTest.cpp +// \brief Source file for the ArraySlice dense general test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + +#include +#include +#include +#include +#include + +// #include +#include +#include + +#include + + +namespace blazetest { + +namespace mathtest { + +namespace arrayslice { + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constructor for the ArraySlice dense general test. +// +// \exception std::runtime_error Operation error detected. +*/ +DenseGeneralTest::DenseGeneralTest() + : mat_ ( 2UL, 5UL, 4UL ) +{ + testConstructors(); + testAssignment(); + testAddAssign(); + testSubAssign(); + testMultAssign(); + testSchurAssign(); + testScaling(); + testFunctionCall(); + testAt(); + testIterator(); + testNonZeros(); + testReset(); + testClear(); + testIsDefault(); + testIsSame(); + testSubmatrix(); + testRow(); + testRows(); + testColumn(); + testColumns(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Test of the ArraySlice constructors. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all constructors of the ArraySlice specialization. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testConstructors() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "ArraySlice constructor (0x0)"; + + MT mat; + + // 0th matrix arrayslice + try { + blaze::arrayslice<2>( mat, 0UL ); + } + catch( std::invalid_argument& ) {} + } + + { + test_ = "ArraySlice constructor (2x0)"; + + MT mat( 2UL, 2UL, 0UL ); + + // 0th matrix arrayslice + { + RT arrayslice0 = blaze::arrayslice<2>( mat, 0UL ); + + checkRows ( arrayslice0, 2UL ); + checkColumns ( arrayslice0, 0UL ); + checkCapacity( arrayslice0, 0UL ); + checkNonZeros( arrayslice0, 0UL ); + } + + // 1st matrix arrayslice + { + RT arrayslice1 = blaze::arrayslice<2>( mat, 1UL ); + + checkRows ( arrayslice1, 2UL ); + checkColumns ( arrayslice1, 0UL ); + checkCapacity( arrayslice1, 0UL ); + checkNonZeros( arrayslice1, 0UL ); + } + + // 2nd matrix arrayslice + try { + blaze::arrayslice<2>( mat, 2UL ); + } + catch( std::invalid_argument& ) {} + } + + { + test_ = "ArraySlice constructor (5x4)"; + + initialize(); + + // 0th tensor arrayslice + { + RT arrayslice0 = blaze::arrayslice<2>( mat_, 0UL ); + + checkRows ( arrayslice0, 5UL ); + checkColumns ( arrayslice0, 4UL ); + checkCapacity( arrayslice0, 20UL ); + checkNonZeros( arrayslice0, 10UL ); + + if( arrayslice0(0,0) != 0 || arrayslice0(0,1) != 0 || arrayslice0(0,2) != 0 || arrayslice0(0,3) != 0 || + arrayslice0(1,0) != 0 || arrayslice0(1,1) != 1 || arrayslice0(1,2) != 0 || arrayslice0(1,3) != 0 || + arrayslice0(2,0) != -2 || arrayslice0(2,1) != 0 || arrayslice0(2,2) != -3 || arrayslice0(2,3) != 0 || + arrayslice0(3,0) != 0 || arrayslice0(3,1) != 4 || arrayslice0(3,2) != 5 || arrayslice0(3,3) != -6 || + arrayslice0(4,0) != 7 || arrayslice0(4,1) != -8 || arrayslice0(4,2) != 9 || arrayslice0(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of 0th dense arrayslice failed\n" + << " Details:\n" + << " Result:\n" << arrayslice0 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // 1st tensor arrayslice + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + + checkRows ( arrayslice1, 5UL ); + checkColumns ( arrayslice1, 4UL ); + checkCapacity( arrayslice1, 20UL ); + checkNonZeros( arrayslice1, 10UL ); + + if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 0 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 0 || + arrayslice1(1,0) != 0 || arrayslice1(1,1) != 1 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || + arrayslice1(2,0) != -2 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != -3 || arrayslice1(2,3) != 0 || + arrayslice1(3,0) != 0 || arrayslice1(3,1) != 4 || arrayslice1(3,2) != 5 || arrayslice1(3,3) != -6 || + arrayslice1(4,0) != 7 || arrayslice1(4,1) != -8 || arrayslice1(4,2) != 9 || arrayslice1(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of 1st dense arrayslice failed\n" + << " Details:\n" + << " Result:\n" << arrayslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // 2nd tensor arrayslice + try { + RT arrayslice2 = blaze::arrayslice<2>( mat_, 2UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Out-of-bound page access succeeded\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief Test of the ArraySlice assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all assignment operators of the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testAssignment() +{ + //===================================================================================== + // homogeneous assignment + //===================================================================================== + + { + test_ = "ArraySlice homogeneous assignment"; + + initialize(); + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice1 = 8; + + + checkRows ( arrayslice1, 5UL ); + checkColumns ( arrayslice1, 4UL ); + checkCapacity( arrayslice1, 20UL ); + checkNonZeros( arrayslice1, 20UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 30UL ); + + if( arrayslice1(0,0) != 8 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 8 || arrayslice1(0,3) != 8 || + arrayslice1(1,0) != 8 || arrayslice1(1,1) != 8 || arrayslice1(1,2) != 8 || arrayslice1(1,3) != 8 || + arrayslice1(2,0) != 8 || arrayslice1(2,1) != 8 || arrayslice1(2,2) != 8 || arrayslice1(2,3) != 8 || + arrayslice1(3,0) != 8 || arrayslice1(3,1) != 8 || arrayslice1(3,2) != 8 || arrayslice1(3,3) != 8 || + arrayslice1(4,0) != 8 || arrayslice1(4,1) != 8 || arrayslice1(4,2) != 8 || arrayslice1(4,3) != 8 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice1 << "\n" + << " Expected result:\n(( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 8 || mat_(1,0,1) != 8 || mat_(1,0,2) != 8 || mat_(1,0,3) != 8 || + mat_(1,1,0) != 8 || mat_(1,1,1) != 8 || mat_(1,1,2) != 8 || mat_(1,1,3) != 8 || + mat_(1,2,0) != 8 || mat_(1,2,1) != 8 || mat_(1,2,2) != 8 || mat_(1,2,3) != 8 || + mat_(1,3,0) != 8 || mat_(1,3,1) != 8 || mat_(1,3,2) != 8 || mat_(1,3,3) != 8 || + mat_(1,4,0) != 8 || mat_(1,4,1) != 8 || mat_(1,4,2) != 8 || mat_(1,4,3) != 8 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 8 8 8 8 )\n" + " ( 8 8 8 8 )\n" + " ( 8 8 8 8 )\n" + " ( 8 8 8 8 )\n" + " ( 8 8 8 8 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // list assignment + //===================================================================================== + + { + test_ = "initializer list assignment (complete list)"; + + initialize(); + + RT arrayslice3 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice3 = { + {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} + }; + + checkRows ( arrayslice3, 5UL ); + checkColumns ( arrayslice3, 4UL ); + checkCapacity( arrayslice3, 20UL ); + checkNonZeros( arrayslice3, 20UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 30UL ); + + if( arrayslice3(0,0) != 1 || arrayslice3(0,1) != 2 || arrayslice3(0,2) != 3 || arrayslice3(0,3) != 4 || + arrayslice3(1,0) != 1 || arrayslice3(1,1) != 2 || arrayslice3(1,2) != 3 || arrayslice3(1,3) != 4 || + arrayslice3(2,0) != 1 || arrayslice3(2,1) != 2 || arrayslice3(2,2) != 3 || arrayslice3(2,3) != 4 || + arrayslice3(3,0) != 1 || arrayslice3(3,1) != 2 || arrayslice3(3,2) != 3 || arrayslice3(3,3) != 4 || + arrayslice3(4,0) != 1 || arrayslice3(4,1) != 2 || arrayslice3(4,2) != 3 || arrayslice3(4,3) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice3 << "\n" + << " Expected result:\n(( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 1 || mat_(1,0,1) != 2 || mat_(1,0,2) != 3 || mat_(1,0,3) != 4 || + mat_(1,1,0) != 1 || mat_(1,1,1) != 2 || mat_(1,1,2) != 3 || mat_(1,1,3) != 4 || + mat_(1,2,0) != 1 || mat_(1,2,1) != 2 || mat_(1,2,2) != 3 || mat_(1,2,3) != 4 || + mat_(1,3,0) != 1 || mat_(1,3,1) != 2 || mat_(1,3,2) != 3 || mat_(1,3,3) != 4 || + mat_(1,4,0) != 1 || mat_(1,4,1) != 2 || mat_(1,4,2) != 3 || mat_(1,4,3) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 1 2 3 4 )\n" + " ( 1 2 3 4 )\n" + " ( 1 2 3 4 )\n" + " ( 1 2 3 4 )\n" + " ( 1 2 3 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "initializer list assignment (incomplete list)"; + + initialize(); + + RT arrayslice3 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice3 = {{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}}; + + checkRows ( arrayslice3, 5UL ); + checkColumns ( arrayslice3, 4UL ); + checkCapacity( arrayslice3, 20UL ); + checkNonZeros( arrayslice3, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice3(0,0) != 1 || arrayslice3(0,1) != 2 || arrayslice3(0,2) != 0 || arrayslice3(0,3) != 0 || + arrayslice3(1,0) != 1 || arrayslice3(1,1) != 2 || arrayslice3(1,2) != 0 || arrayslice3(1,3) != 0 || + arrayslice3(2,0) != 1 || arrayslice3(2,1) != 2 || arrayslice3(2,2) != 0 || arrayslice3(2,3) != 0 || + arrayslice3(3,0) != 1 || arrayslice3(3,1) != 2 || arrayslice3(3,2) != 0 || arrayslice3(3,3) != 0 || + arrayslice3(4,0) != 1 || arrayslice3(4,1) != 2 || arrayslice3(4,2) != 0 || arrayslice3(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice3 << "\n" + << " Expected result:\n(( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 1 || mat_(1,0,1) != 2 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 1 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 1 || mat_(1,2,1) != 2 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 1 || mat_(1,3,1) != 2 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 1 || mat_(1,4,1) != 2 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 1 2 0 0 )\n" + " ( 1 2 0 0 )\n" + " ( 1 2 0 0 )\n" + " ( 1 2 0 0 )\n" + " ( 1 2 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // copy assignment + //===================================================================================== + + { + test_ = "ArraySlice copy assignment"; + + initialize(); + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 0UL ); + arrayslice1 = 0; + arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + + checkRows ( arrayslice1, 5UL ); + checkColumns ( arrayslice1, 4UL ); + checkCapacity( arrayslice1, 20UL ); + checkNonZeros( arrayslice1, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 0 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 0 || + arrayslice1(1,0) != 0 || arrayslice1(1,1) != 1 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || + arrayslice1(2,0) != -2 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != -3 || arrayslice1(2,3) != 0 || + arrayslice1(3,0) != 0 || arrayslice1(3,1) != 4 || arrayslice1(3,2) != 5 || arrayslice1(3,3) != -6 || + arrayslice1(4,0) != 7 || arrayslice1(4,1) != -8 || arrayslice1(4,2) != 9 || arrayslice1(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense array assignment + //===================================================================================== + + { + test_ = "dense array assignment (mixed type)"; + + initialize(); + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + + blaze::DynamicArray<2, int> m1; + m1 = {{0, 8, 0, 9}, {0}, {0}, {0}, {0}}; + + arrayslice1 = m1; + + checkRows ( arrayslice1, 5UL ); + checkColumns ( arrayslice1, 4UL ); + checkCapacity( arrayslice1, 20UL ); + checkNonZeros( arrayslice1, 2UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 12UL ); + + if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 9 || + arrayslice1(1,0) != 0 || arrayslice1(1,1) != 0 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || + arrayslice1(2,0) != 0 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != 0 || arrayslice1(2,3) != 0 || + arrayslice1(3,0) != 0 || arrayslice1(3,1) != 0 || arrayslice1(3,2) != 0 || arrayslice1(3,3) != 0 || + arrayslice1(4,0) != 0 || arrayslice1(4,1) != 0 || arrayslice1(4,2) != 0 || arrayslice1(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice1 << "\n" + << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 8 || mat_(1,0,2) != 0 || mat_(1,0,3) != 9 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 9 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + initialize(); + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + + using AlignedPadded = blaze::CustomMatrix; + std::unique_ptr memory( blaze::allocate( 80UL ) ); + AlignedPadded m1( memory.get(), 5UL, 4UL, 16UL ); + m1 = 0; + m1(0,0) = 0; + m1(0,1) = 8; + m1(0,2) = 0; + m1(0,3) = 9; + + arrayslice1 = m1; + + checkRows ( arrayslice1, 5UL ); + checkColumns ( arrayslice1, 4UL ); + checkCapacity( arrayslice1, 20UL ); + checkNonZeros( arrayslice1, 2UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 12UL ); + + if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 9 || + arrayslice1(1,0) != 0 || arrayslice1(1,1) != 0 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || + arrayslice1(2,0) != 0 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != 0 || arrayslice1(2,3) != 0 || + arrayslice1(3,0) != 0 || arrayslice1(3,1) != 0 || arrayslice1(3,2) != 0 || arrayslice1(3,3) != 0 || + arrayslice1(4,0) != 0 || arrayslice1(4,1) != 0 || arrayslice1(4,2) != 0 || arrayslice1(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice1 << "\n" + << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 8 || mat_(1,0,2) != 0 || mat_(1,0,3) != 9 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 9 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + initialize(); + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + + using UnalignedUnpadded = blaze::CustomMatrix; + std::unique_ptr memory( new int[21] ); + UnalignedUnpadded m1( memory.get()+1UL, 5UL, 4UL ); + m1 = 0; + m1(0,0) = 0; + m1(0,1) = 8; + m1(0,2) = 0; + m1(0,3) = 9; + + arrayslice1 = m1; + + checkRows ( arrayslice1, 5UL ); + checkColumns ( arrayslice1, 4UL ); + checkCapacity( arrayslice1, 20UL ); + checkNonZeros( arrayslice1, 2UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 12UL ); + + if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 9 || + arrayslice1(1,0) != 0 || arrayslice1(1,1) != 0 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || + arrayslice1(2,0) != 0 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != 0 || arrayslice1(2,3) != 0 || + arrayslice1(3,0) != 0 || arrayslice1(3,1) != 0 || arrayslice1(3,2) != 0 || arrayslice1(3,3) != 0 || + arrayslice1(4,0) != 0 || arrayslice1(4,1) != 0 || arrayslice1(4,2) != 0 || arrayslice1(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice1 << "\n" + << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 8 || mat_(1,0,2) != 0 || mat_(1,0,3) != 9 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 9 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice addition assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the addition assignment operators of the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testAddAssign() +{ + //===================================================================================== + // ArraySlice addition assignment + //===================================================================================== + + { + test_ = "ArraySlice addition assignment"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 += blaze::arrayslice<2>( mat_, 0UL ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || + arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || + mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense array addition assignment + //===================================================================================== + + { + test_ = "dense array addition assignment (mixed type)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + const blaze::DynamicMatrix vec{{0, 0, 0, 0}, + {0, 1, 0, 0}, + {-2, 0, -3, 0}, + {0, 4, 5, -6}, + {7, -8, 9, 10}}; + + arrayslice2 += vec; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || + arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || + mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array addition assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + using AlignedPadded = blaze::CustomMatrix; + std::unique_ptr memory( blaze::allocate( 80UL ) ); + AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); + m(0,0) = 0; + m(0,1) = 0; + m(0,2) = 0; + m(0,3) = 0; + m(1,0) = 0; + m(1,1) = 1; + m(1,2) = 0; + m(1,3) = 0; + m(2,0) = -2; + m(2,1) = 0; + m(2,2) = -3; + m(2,3) = 0; + m(3,0) = 0; + m(3,1) = 4; + m(3,2) = 5; + m(3,3) = -6; + m(4,0) = 7; + m(4,1) = -8; + m(4,2) = 9; + m(4,3) = 10; + + arrayslice2 += m; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || + arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || + mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array addition assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + using UnalignedUnpadded = blaze::CustomMatrix; + std::unique_ptr memory( new int[21] ); + UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); + m(0,0) = 0; + m(0,1) = 0; + m(0,2) = 0; + m(0,3) = 0; + m(1,0) = 0; + m(1,1) = 1; + m(1,2) = 0; + m(1,3) = 0; + m(2,0) = -2; + m(2,1) = 0; + m(2,2) = -3; + m(2,3) = 0; + m(3,0) = 0; + m(3,1) = 4; + m(3,2) = 5; + m(3,3) = -6; + m(4,0) = 7; + m(4,1) = -8; + m(4,2) = 9; + m(4,3) = 10; + + arrayslice2 += m; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || + arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || + mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice subtraction assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the subtraction assignment operators of the ArraySlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testSubAssign() +{ + //===================================================================================== + // ArraySlice subtraction assignment + //===================================================================================== + + { + test_ = "ArraySlice subtraction assignment"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 -= blaze::arrayslice<2>( mat_, 0UL ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 0UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || + arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense array subtraction assignment + //===================================================================================== + + { + test_ = "dense array subtraction assignment (mixed type)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + const blaze::DynamicMatrix vec{{0, 0, 0, 0}, + {0, 1, 0, 0}, + {-2, 0, -3, 0}, + {0, 4, 5, -6}, + {7, -8, 9, 10}}; + + arrayslice2 -= vec; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 0UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || + arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + } + } + + { + test_ = "dense array subtraction assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + using AlignedPadded = blaze::CustomMatrix; + std::unique_ptr memory( blaze::allocate( 80UL ) ); + AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); + m(0,0) = 0; + m(0,1) = 0; + m(0,2) = 0; + m(0,3) = 0; + m(1,0) = 0; + m(1,1) = 1; + m(1,2) = 0; + m(1,3) = 0; + m(2,0) = -2; + m(2,1) = 0; + m(2,2) = -3; + m(2,3) = 0; + m(3,0) = 0; + m(3,1) = 4; + m(3,2) = 5; + m(3,3) = -6; + m(4,0) = 7; + m(4,1) = -8; + m(4,2) = 9; + m(4,3) = 10; + + arrayslice2 -= m; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 0UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || + arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array subtraction assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + using UnalignedUnpadded = blaze::CustomMatrix; + std::unique_ptr memory( new int[21] ); + UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); + m(0,0) = 0; + m(0,1) = 0; + m(0,2) = 0; + m(0,3) = 0; + m(1,0) = 0; + m(1,1) = 1; + m(1,2) = 0; + m(1,3) = 0; + m(2,0) = -2; + m(2,1) = 0; + m(2,2) = -3; + m(2,3) = 0; + m(3,0) = 0; + m(3,1) = 4; + m(3,2) = 5; + m(3,3) = -6; + m(4,0) = 7; + m(4,1) = -8; + m(4,2) = 9; + m(4,3) = 10; + + arrayslice2 -= m; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 0UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || + arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice multiplication assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the multiplication assignment operators of the ArraySlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testMultAssign() +{ + //===================================================================================== + // ArraySlice multiplication assignment + //===================================================================================== + + { + test_ = "ArraySlice multiplication assignment"; + + initialize(); + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + arrayslice2 *= blaze::arrayslice<2>( m, 0UL ); + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || + arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || + arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || + m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || + m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 90 114 138 )\n" + " ( 54 69 84 )\n" + " ( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense array multiplication assignment + //===================================================================================== + + { + test_ = "dense array multiplication assignment (mixed type)"; + + initialize(); + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + + const blaze::DynamicMatrix m1{ + {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + + arrayslice2 *= m1; + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || + arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || + arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || + m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || + m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 90 114 138 )\n" + " ( 54 69 84 )\n" + " ( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array multiplication assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + + + using AlignedPadded = blaze::CustomMatrix; + std::unique_ptr memory( blaze::allocate( 48UL ) ); + AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); + m1(0,0) = 1; + m1(0,1) = 2; + m1(0,2) = 3; + m1(1,0) = 4; + m1(1,1) = 5; + m1(1,2) = 6; + m1(2,0) = 7; + m1(2,1) = 8; + m1(2,2) = 9; + + arrayslice2 *= m1; + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || + arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || + arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || + m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || + m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 90 114 138 )\n" + " ( 54 69 84 )\n" + " ( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array multiplication assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + + using UnalignedUnpadded = blaze::CustomMatrix; + std::unique_ptr memory( new int[10] ); + UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); + m1(0,0) = 1; + m1(0,1) = 2; + m1(0,2) = 3; + m1(1,0) = 4; + m1(1,1) = 5; + m1(1,2) = 6; + m1(2,0) = 7; + m1(2,1) = 8; + m1(2,2) = 9; + + arrayslice2 *= m1; + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || + arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || + arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || + m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || + m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 90 114 138 )\n" + " ( 54 69 84 )\n" + " ( 18 24 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice Schur product assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the Schur product assignment operators of the ArraySlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testSchurAssign() +{ + //===================================================================================== + // ArraySlice Schur product assignment + //===================================================================================== + + { + test_ = "ArraySlice Schur product assignment"; + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + arrayslice2 %= blaze::arrayslice<2>( m, 0UL ); + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || + arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || + arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || + m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || + m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense array Schur product assignment + //===================================================================================== + + { + test_ = "dense vector Schur product assignment (mixed type)"; + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + + const blaze::DynamicMatrix m1{ + {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + + arrayslice2 %= m1; + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || + arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || + arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || + m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || + m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array Schur product assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + + using AlignedPadded = blaze::CustomMatrix; + std::unique_ptr memory( blaze::allocate( 48UL ) ); + AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); + m1(0,0) = 1; + m1(0,1) = 2; + m1(0,2) = 3; + m1(1,0) = 4; + m1(1,1) = 5; + m1(1,2) = 6; + m1(2,0) = 7; + m1(2,1) = 8; + m1(2,2) = 9; + + arrayslice2 %= m1; + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || + arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || + arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || + m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || + m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense array Schur product assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); + + using UnalignedUnpadded = blaze::CustomMatrix; + std::unique_ptr memory( new int[10] ); + UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); + m1(0,0) = 1; + m1(0,1) = 2; + m1(0,2) = 3; + m1(1,0) = 4; + m1(1,1) = 5; + m1(1,2) = 6; + m1(2,0) = 7; + m1(2,1) = 8; + m1(2,2) = 9; + + arrayslice2 %= m1; + + checkRows ( arrayslice2, 3UL ); + checkColumns ( arrayslice2, 3UL ); + checkCapacity( arrayslice2, 9UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( m, 3UL ); + checkColumns ( m, 3UL ); + checkPages ( m, 2UL ); + checkNonZeros( m, 18UL ); + + if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || + arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || + arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || + m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || + m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || + m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || + m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || + m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of all ArraySlice (self-)scaling operations. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all available ways to scale an instance of the ArraySlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testScaling() +{ + //===================================================================================== + // self-scaling (v*=2) + //===================================================================================== + + { + test_ = "self-scaling (v*=2)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 *= 3; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || + arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || + mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 3 0 0 )\n" + " ( -6 0 -9 0 )\n" + " ( 0 12 15 -18 )\n" + " ( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v=v*2) + //===================================================================================== + + { + test_ = "self-scaling (v=v*3)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 = arrayslice2 * 3; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || + arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || + mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 3 0 0 )\n" + " ( -6 0 -9 0 )\n" + " ( 0 12 15 -18 )\n" + " ( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v=3*v) + //===================================================================================== + + { + test_ = "self-scaling (v=3*v)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 = 3 * arrayslice2; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || + arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || + mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 3 0 0 )\n" + " ( -6 0 -9 0 )\n" + " ( 0 12 15 -18 )\n" + " ( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v/=s) + //===================================================================================== + + { + test_ = "self-scaling (v/=s)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 /= (1.0/3.0); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || + arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || + mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 3 0 0 )\n" + " ( -6 0 -9 0 )\n" + " ( 0 12 15 -18 )\n" + " ( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v=v/s) + //===================================================================================== + + { + test_ = "self-scaling (v=v/s)"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2 = arrayslice2 / (1.0/3.0); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || + arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || + mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 3 0 0 )\n" + " ( -6 0 -9 0 )\n" + " ( 0 12 15 -18 )\n" + " ( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // ArraySlice::scale() + //===================================================================================== + + { + test_ = "ArraySlice::scale()"; + + initialize(); + + // Integral scaling the 3rd arrayslice + { + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2.scale( 3 ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || + arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || + mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 3 0 0 )\n" + " ( -6 0 -9 0 )\n" + " ( 0 12 15 -18 )\n" + " ( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + initialize(); + + // Floating point scaling the 3rd arrayslice + { + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + arrayslice2.scale( 0.5 ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 19UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -1 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -1 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 2 || arrayslice2(3,2) != 2 || arrayslice2(3,3) != -3 || + arrayslice2(4,0) != 3 || arrayslice2(4,1) != -4 || arrayslice2(4,2) != 4 || arrayslice2(4,3) != 5 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( -1 0 -1 0 )\n( 0 12 2 -3 )\n( 3 -4 4 5 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -1 || mat_(1,2,1) != 0 || mat_(1,2,2) != -1 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 2 || mat_(1,3,2) != 2 || mat_(1,3,3) != -3 || + mat_(1,4,0) != 3 || mat_(1,4,1) != -4 || mat_(1,4,2) != 4 || mat_(1,4,3) != 5 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( -1 0 -1 0 )\n" + " ( 0 2 2 -3 )\n" + " ( 3 -4 4 5 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice function call operator. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of adding and accessing elements via the function call operator +// of the ArraySlice specialization. In case an error is detected, a \a std::runtime_error exception +// is thrown. +*/ +void DenseGeneralTest::testFunctionCall() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "ArraySlice::operator()"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + // Assignment to the element at index (0,1) + arrayslice2(0,1) = 9; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 11UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 21UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 9 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (2,2) + arrayslice2(2,2) = 0; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 9 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (4,1) + arrayslice2(4,1) = -9; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 9 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Addition assignment to the element at index (0,1) + arrayslice2(0,1) += -3; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Subtraction assignment to the element at index (2,0) + arrayslice2(2,0) -= 6; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -8 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -8 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Multiplication assignment to the element at index (4,0) + arrayslice2(4,0) *= -3; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -8 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != -21 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -8 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Division assignment to the element at index (3,3) + arrayslice2(3,3) /= 2; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -8 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -3 || + arrayslice2(4,0) != -21 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -3 || + mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -8 0 0 0 )\n" + " ( 0 4 5 -3 )\n" + " ( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice at() operator. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of adding and accessing elements via the at() operator +// of the ArraySlice specialization. In case an error is detected, a \a std::runtime_error exception +// is thrown. +*/ +void DenseGeneralTest::testAt() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "ArraySlice::at()"; + + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + // Assignment to the element at index (0,1) + arrayslice2.at(0,1) = 9; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 11UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 21UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 9 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != -3 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || + arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -8 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (2,2) + arrayslice2.at(2,2) = 0; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 9 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || + arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -8 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (4,1) + arrayslice2.at(4,1) = -9; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 9 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || + arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 9 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Addition assignment to the element at index (0,1) + arrayslice2.at(0,1) += -3; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || + arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Subtraction assignment to the element at index (2,0) + arrayslice2.at(2,0) -= 6; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -8 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || + arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -8 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Multiplication assignment to the element at index (4,0) + arrayslice2.at(4,0) *= -3; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -8 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || + arrayslice2.at(4,0) != -21 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -8 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Division assignment to the element at index (3,3) + arrayslice2.at(3,3) /= 2; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || + arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || + arrayslice2.at(2,0) != -8 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || + arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -3 || + arrayslice2.at(4,0) != -21 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -3 || + mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: At() failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 6 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -8 0 0 0 )\n" + " ( 0 4 5 -3 )\n" + " ( -21 -9 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the ArraySlice iterator implementation. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the iterator implementation of the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testIterator() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + initialize(); + + // Testing the Iterator default constructor + { + test_ = "Iterator default constructor"; + + RT::Iterator it{}; + + if( it != RT::Iterator() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator default constructor\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing the ConstIterator default constructor + { + test_ = "ConstIterator default constructor"; + + RT::ConstIterator it{}; + + if( it != RT::ConstIterator() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator default constructor\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing conversion from Iterator to ConstIterator + { + test_ = "Iterator/ConstIterator conversion"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + RT::ConstIterator it( begin( arrayslice2, 2UL ) ); + + if( it == end( arrayslice2, 2UL ) || *it != -2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator conversion detected\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 1st arrayslice via Iterator (end-begin) + { + test_ = "Iterator subtraction (end-begin)"; + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + const ptrdiff_t number( end( arrayslice1, 2UL ) - begin( arrayslice1, 2UL ) ); + + if( number != 4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: 4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 1st arrayslice via Iterator (begin-end) + { + test_ = "Iterator subtraction (begin-end)"; + + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + const ptrdiff_t number( begin( arrayslice1, 2UL ) - end( arrayslice1, 2UL ) ); + + if( number != -4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: -4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 2nd arrayslice via ConstIterator (end-begin) + { + test_ = "ConstIterator subtraction (end-begin)"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + const ptrdiff_t number( cend( arrayslice2, 2UL ) - cbegin( arrayslice2, 2UL ) ); + + if( number != 4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: 4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 2nd arrayslice via ConstIterator (begin-end) + { + test_ = "ConstIterator subtraction (begin-end)"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + const ptrdiff_t number( cbegin( arrayslice2, 2UL ) - cend( arrayslice2, 2UL ) ); + + if( number != -4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: -4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing read-only access via ConstIterator + { + test_ = "read-only access via ConstIterator"; + + RT arrayslice3 = blaze::arrayslice<2>( mat_, 0UL ); + RT::ConstIterator it ( cbegin( arrayslice3, 4UL ) ); + RT::ConstIterator end( cend( arrayslice3, 4UL ) ); + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid initial iterator detected\n"; + throw std::runtime_error( oss.str() ); + } + + ++it; + + if( it == end || *it != -8 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator pre-increment failed\n"; + throw std::runtime_error( oss.str() ); + } + + --it; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator pre-decrement failed\n"; + throw std::runtime_error( oss.str() ); + } + + it++; + + if( it == end || *it != -8 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator post-increment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it--; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator post-decrement failed\n"; + throw std::runtime_error( oss.str() ); + } + + it += 2UL; + + if( it == end || *it != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator addition assignment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it -= 2UL; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator subtraction assignment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = it + 3UL; + + if( it == end || *it != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator/scalar addition failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = it - 3UL; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator/scalar subtraction failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = 4UL + it; + + if( it != end ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Scalar/iterator addition failed\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing assignment via Iterator + { + test_ = "assignment via Iterator"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + int value = 6; + + for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { + *it = value++; + } + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 6 || arrayslice2(4,1) != 7 || arrayslice2(4,2) != 8 || arrayslice2(4,3) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 6 || mat_(1,4,1) != 7 || mat_(1,4,2) != 8 || mat_(1,4,3) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 6 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing addition assignment via Iterator + { + test_ = "addition assignment via Iterator"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + int value = 2; + + for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { + *it += value++; + } + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 8 || arrayslice2(4,1) != 10 || arrayslice2(4,2) != 12 || arrayslice2(4,3) != 14 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 8 10 12 14 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 8 || mat_(1,4,1) != 10 || mat_(1,4,2) != 12 || mat_(1,4,3) != 14 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 8 10 12 14 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing subtraction assignment via Iterator + { + test_ = "subtraction assignment via Iterator"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + int value = 2; + + for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { + *it -= value++; + } + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 6 || arrayslice2(4,1) != 7 || arrayslice2(4,2) != 8 || arrayslice2(4,3) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 6 || mat_(1,4,1) != 7 || mat_(1,4,2) != 8 || mat_(1,4,3) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 6 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing multiplication assignment via Iterator + { + test_ = "multiplication assignment via Iterator"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + int value = 1; + + for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { + *it *= value++; + } + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 6 || arrayslice2(4,1) != 14 || arrayslice2(4,2) != 24 || arrayslice2(4,3) != 36 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 14 24 36 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 6 || mat_(1,4,1) != 14 || mat_(1,4,2) != 24 || mat_(1,4,3) != 36 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 6 14 24 36 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing division assignment via Iterator + { + test_ = "division assignment via Iterator"; + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { + *it /= 2; + } + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 3 || arrayslice2(4,1) != 7 || arrayslice2(4,2) != 12 || arrayslice2(4,3) != 18 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Division assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 3 7 12 18 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || + mat_(1,4,0) != 3 || mat_(1,4,1) != 7 || mat_(1,4,2) != 12 || mat_(1,4,3) != 18 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Division assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 0 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 3 7 12 18 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c nonZeros() member function of the ArraySlice specialization. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c nonZeros() member function of the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testNonZeros() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "ArraySlice::nonZeros()"; + + initialize(); + + // Initialization check + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Changing the number of non-zeros via the dense arrayslice + arrayslice2(2, 2) = 0; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 19UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Changing the number of non-zeros via the dense array + mat_(1,3,0) = 5; + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 10UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 20UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 5 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Matrix function call operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 5 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c reset() member function of the ArraySlice specialization. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c reset() member function of the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testReset() +{ + using blaze::reset; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "ArraySlice::reset()"; + + // Resetting a single element in arrayslice 3 + { + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + reset( arrayslice2(2, 2) ); + + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 19UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operator failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Resetting the 1st arrayslice (lvalue) + { + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + reset( arrayslice2 ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 0UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || + arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation of 1st arrayslice failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Resetting the 1st arrayslice (rvalue) + { + initialize(); + + reset( blaze::arrayslice<2>( mat_, 1UL ) ); + + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation of 1st arrayslice failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c clear() function with the ArraySlice specialization. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c clear() function with the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testClear() +{ + using blaze::clear; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "clear() function"; + + // Clearing a single element in arrayslice 1 + { + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + clear( arrayslice2(2, 2) ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 9UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 19UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || + arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Clear operation failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Clearing the 3rd arrayslice (lvalue) + { + initialize(); + + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + clear( arrayslice2 ); + + checkRows ( arrayslice2, 5UL ); + checkColumns ( arrayslice2, 4UL ); + checkCapacity( arrayslice2, 20UL ); + checkNonZeros( arrayslice2, 0UL ); + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || + arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || + arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || + arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || + arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Clear operation of 3rd arrayslice failed\n" + << " Details:\n" + << " Result:\n" << arrayslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Clearing the 4th arrayslice (rvalue) + { + initialize(); + + clear( blaze::arrayslice<2>( mat_, 1UL ) ); + + checkRows ( mat_, 5UL ); + checkColumns ( mat_, 4UL ); + checkPages ( mat_, 2UL ); + checkNonZeros( mat_, 10UL ); + + if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || + mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || + mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || + mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || + mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || + mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || + mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || + mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || + mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || + mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Clear operation of 1st arrayslice failed\n" + << " Details:\n" + << " Result:\n" << mat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isDefault() function with the ArraySlice specialization. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isDefault() function with the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testIsDefault() +{ + using blaze::isDefault; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "isDefault() function"; + + initialize(); + + // isDefault with default arrayslice + { + RT arrayslice0 = blaze::arrayslice<2>( mat_, 0UL ); + arrayslice0 = 0; + + if( isDefault( arrayslice0(0, 0) ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " ArraySlice element: " << arrayslice0(0, 0) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( isDefault( arrayslice0 ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " ArraySlice:\n" << arrayslice0 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isDefault with non-default arrayslice + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + + if( isDefault( arrayslice1(1, 1) ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " ArraySlice element: " << arrayslice1(1, 1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( isDefault( arrayslice1 ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " ArraySlice:\n" << arrayslice1 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isSame() function with the ArraySlice specialization. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isSame() function with the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testIsSame() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "isSame() function"; + + // isSame with matching arrayslices + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 0UL ); + RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); + + arrayslice1 = 42; + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with arrayslice and matching submatrix + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto sv = blaze::submatrix( arrayslice1, 0UL, 0UL, 5UL, 4UL ); + + if( blaze::isSame( arrayslice1, sv ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense arrayslice:\n" << arrayslice1 << "\n" + << " Dense submatrix:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( sv, arrayslice1 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense arrayslice:\n" << arrayslice1 << "\n" + << " Dense submatrix:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with arrayslice and non-matching submatrix (different size) + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto sv = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 3UL ); + + if( blaze::isSame( arrayslice1, sv ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense arrayslice:\n" << arrayslice1 << "\n" + << " Dense submatrix:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( sv, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense arrayslice:\n" << arrayslice1 << "\n" + << " Dense submatrix:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with arrayslice and non-matching submatrix (different offset) + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto sv = blaze::submatrix( arrayslice1, 1UL, 1UL, 3UL, 3UL ); + + if( blaze::isSame( arrayslice1, sv ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense arrayslice:\n" << arrayslice1 << "\n" + << " Dense submatrix:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( sv, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense arrayslice:\n" << arrayslice1 << "\n" + << " Dense submatrix:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with matching arrayslices on a common subtensor + { + auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm, 1UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices on a common subtensor + { + auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm, 0UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm, 1UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with matching subtensor on matrix and subtensor + { + auto sm = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm , 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices on tensor and subtensor (different arrayslice) + { + auto sm = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( mat_, 0UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm , 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices on tensor and subtensor (different size) + { + auto sm = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 4UL, 3UL ); + auto arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm , 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with matching arrayslices on two subtensors + { + auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices on two subtensors (different arrayslice) + { + auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 0UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices on two subtensors (different size) + { + auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 4UL, 3UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslices on two subtensors (different offset) + { + auto sm1 = blaze::subtensor( mat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 4UL, 2UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + + if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First arrayslice:\n" << arrayslice1 << "\n" + << " Second arrayslice:\n" << arrayslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with matching arrayslice submatrices on a subtensor + { + auto sm = blaze::subtensor( mat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); + auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); + auto sv2 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); + + if( blaze::isSame( sv1, sv2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First submatrix:\n" << sv1 << "\n" + << " Second submatrix:\n" << sv2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslice subtensors on a submatrix (different size) + { + auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); + auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); + auto sv2 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 2UL ); + + if( blaze::isSame( sv1, sv2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First submatrix:\n" << sv1 << "\n" + << " Second submatrix:\n" << sv2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslice subtensors on a submatrix (different offset) + { + auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); + auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); + auto sv2 = blaze::submatrix( arrayslice1, 0UL, 1UL, 2UL, 1UL ); + + if( blaze::isSame( sv1, sv2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First submatrix:\n" << sv1 << "\n" + << " Second submatrix:\n" << sv2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with matching arrayslice subtensors on two subtensors + { + auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 2UL ); + auto sv2 = blaze::submatrix( arrayslice2, 0UL, 0UL, 3UL, 2UL ); + + if( blaze::isSame( sv1, sv2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First submatrix:\n" << sv1 << "\n" + << " Second submatrix:\n" << sv2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslice subtensors on two subtensors (different size) + { + auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 2UL ); + auto sv2 = blaze::submatrix( arrayslice2, 0UL, 0UL, 2UL, 2UL ); + + if( blaze::isSame( sv1, sv2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First submatrix:\n" << sv1 << "\n" + << " Second submatrix:\n" << sv2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching arrayslice subtensors on two subtensors (different offset) + { + auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); + auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); + auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); + auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); + auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 2UL ); + auto sv2 = blaze::submatrix( arrayslice2, 0UL, 1UL, 3UL, 2UL ); + + if( blaze::isSame( sv1, sv2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First submatrix:\n" << sv1 << "\n" + << " Second submatrix:\n" << sv2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c submatrix() function with the ArraySlice specialization. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c submatrix() function used with the ArraySlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testSubmatrix() +{ + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "submatrix() function"; + + initialize(); + + { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto sm = blaze::submatrix( arrayslice1, 1UL, 1UL, 2UL, 3UL ); + + if( sm(0,0) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << sm(0,0) << "\n" + << " Expected result: 1\n"; + throw std::runtime_error( oss.str() ); + } + + if( *sm.begin(1) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *sm.begin(1) << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto sm = blaze::submatrix( arrayslice1, 4UL, 0UL, 4UL, 4UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds submatrix succeeded\n" + << " Details:\n" + << " Result:\n" << sm << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + + try { + RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); + auto sm = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 6UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds submatrix succeeded\n" + << " Details:\n" + << " Result:\n" << sm << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief Test of the \c row() function with the Submatrix class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c row() function with the Submatrix specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testRow() +{ + using blaze::arrayslice; + using blaze::row; + using blaze::aligned; + using blaze::unaligned; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "Pageslice row() function"; + + initialize(); + + { + RT arrayslice1 = arrayslice( mat_, 0UL ); + RT arrayslice2 = arrayslice( mat_, 1UL ); + auto row1 = row( arrayslice1, 1UL ); + auto row2 = row( arrayslice2, 1UL ); + + if( row1 != row2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Row function failed\n" + << " Details:\n" + << " Result:\n" << row1 << "\n" + << " Expected result:\n" << row2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( row1[1] != row2[1] ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << row1[1] << "\n" + << " Expected result: " << row2[1] << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *row1.begin() != *row2.begin() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *row1.begin() << "\n" + << " Expected result: " << *row2.begin() << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT arrayslice1 = arrayslice( mat_, 0UL ); + auto row8 = row( arrayslice1, 8UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds row succeeded\n" + << " Details:\n" + << " Result:\n" << row8 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c rows() function with the Submatrix class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c rows() function with the Submatrix specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testRows() +{ + using blaze::arrayslice; + using blaze::rows; + using blaze::aligned; + using blaze::unaligned; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "Pageslice rows() function"; + + initialize(); + + { + RT arrayslice1 = arrayslice( mat_, 0UL ); + RT arrayslice2 = arrayslice( mat_, 1UL ); + auto rs1 = rows( arrayslice1, { 0UL, 2UL, 4UL, 3UL } ); + auto rs2 = rows( arrayslice2, { 0UL, 2UL, 4UL, 3UL } ); + + if( rs1 != rs2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Rows function failed\n" + << " Details:\n" + << " Result:\n" << rs1 << "\n" + << " Expected result:\n" << rs2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( rs1(1,1) != rs2(1,1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator access failed\n" + << " Details:\n" + << " Result: " << rs1(1,1) << "\n" + << " Expected result: " << rs2(1,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *rs1.begin( 1UL ) != *rs2.begin( 1UL ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *rs1.begin( 1UL ) << "\n" + << " Expected result: " << *rs2.begin( 1UL ) << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT arrayslice1 = arrayslice( mat_, 1UL ); + auto rs = rows( arrayslice1, { 8UL } ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds row selection succeeded\n" + << " Details:\n" + << " Result:\n" << rs << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c column() function with the Submatrix class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c column() function with the Submatrix specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testColumn() +{ + using blaze::arrayslice; + using blaze::column; + using blaze::aligned; + using blaze::unaligned; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "Pageslice column() function"; + + initialize(); + + { + RT arrayslice1 = arrayslice( mat_, 0UL ); + RT arrayslice2 = arrayslice( mat_, 1UL ); + auto col1 = column( arrayslice1, 1UL ); + auto col2 = column( arrayslice2, 1UL ); + + if( col1 != col2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Column function failed\n" + << " Details:\n" + << " Result:\n" << col1 << "\n" + << " Expected result:\n" << col2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( col1[1] != col2[1] ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << col1[1] << "\n" + << " Expected result: " << col2[1] << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *col1.begin() != *col2.begin() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *col1.begin() << "\n" + << " Expected result: " << *col2.begin() << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT arrayslice1 = arrayslice( mat_, 0UL ); + auto col16 = column( arrayslice1, 16UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds column succeeded\n" + << " Details:\n" + << " Result:\n" << col16 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c columns() function with the Submatrix class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c columns() function with the Submatrix specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testColumns() +{ + using blaze::arrayslice; + using blaze::rows; + using blaze::aligned; + using blaze::unaligned; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "columns() function"; + + initialize(); + + { + RT arrayslice1 = arrayslice( mat_, 0UL ); + RT arrayslice2 = arrayslice( mat_, 1UL ); + auto cs1 = columns( arrayslice1, { 0UL, 2UL, 2UL, 3UL } ); + auto cs2 = columns( arrayslice2, { 0UL, 2UL, 2UL, 3UL } ); + + if( cs1 != cs2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Rows function failed\n" + << " Details:\n" + << " Result:\n" << cs1 << "\n" + << " Expected result:\n" << cs2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( cs1(1,1) != cs2(1,1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator access failed\n" + << " Details:\n" + << " Result: " << cs1(1,1) << "\n" + << " Expected result: " << cs2(1,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *cs1.begin( 1UL ) != *cs2.begin( 1UL ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *cs1.begin( 1UL ) << "\n" + << " Expected result: " << *cs2.begin( 1UL ) << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT arrayslice1 = arrayslice( mat_, 1UL ); + auto cs = columns( arrayslice1, { 16UL } ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds column selection succeeded\n" + << " Details:\n" + << " Result:\n" << cs << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c band() function with the Submatrix class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c band() function with the Submatrix specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testBand() +{ + using blaze::arrayslice; + using blaze::band; + using blaze::aligned; + using blaze::unaligned; + + + //===================================================================================== + // matrix tests + //===================================================================================== + + { + test_ = "Pageslice band() function"; + + initialize(); + + { + RT arrayslice1 = arrayslice( mat_, 0UL ); + RT arrayslice2 = arrayslice( mat_, 1UL ); + auto b1 = band( arrayslice1, 1L ); + auto b2 = band( arrayslice2, 1L ); + + if( b1 != b2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Band function failed\n" + << " Details:\n" + << " Result:\n" << b1 << "\n" + << " Expected result:\n" << b2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( b1[1] != b2[1] ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << b1[1] << "\n" + << " Expected result: " << b2[1] << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *b1.begin() != *b2.begin() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *b1.begin() << "\n" + << " Expected result: " << *b2.begin() << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT arrayslice1 = arrayslice( mat_, 1UL ); + auto b8 = band( arrayslice1, -8L ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds band succeeded\n" + << " Details:\n" + << " Result:\n" << b8 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Initialization of all member matrices. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function initializes all member matrices to specific predetermined values. +*/ +void DenseGeneralTest::initialize() +{ + // Initializing the arrayslice-major dynamic matrix + mat_.reset(); + mat_(0,1,1) = 1; + mat_(0,2,0) = -2; + mat_(0,2,2) = -3; + mat_(0,3,1) = 4; + mat_(0,3,2) = 5; + mat_(0,3,3) = -6; + mat_(0,4,0) = 7; + mat_(0,4,1) = -8; + mat_(0,4,2) = 9; + mat_(0,4,3) = 10; + mat_(1,1,1) = 1; + mat_(1,2,0) = -2; + mat_(1,2,2) = -3; + mat_(1,3,1) = 4; + mat_(1,3,2) = 5; + mat_(1,3,3) = -6; + mat_(1,4,0) = 7; + mat_(1,4,1) = -8; + mat_(1,4,2) = 9; + mat_(1,4,3) = 10; +} +//************************************************************************************************* + +} // namespace arrayslice + +} // namespace mathtest + +} // namespace blazetest + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + std::cout << " Running ArraySlice dense general test..." << std::endl; + + try + { + RUN_PAGESLICE_DENSEGENERAL_TEST; + } + catch( std::exception& ex ) { + std::cerr << "\n\n ERROR DETECTED during ArraySlice dense general test:\n" + << ex.what() << "\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +//************************************************************************************************* diff --git a/blazetest/src/mathtest/arrayslice/IncludeTest.cpp b/blazetest/src/mathtest/arrayslice/IncludeTest.cpp new file mode 100644 index 0000000..3f3b2af --- /dev/null +++ b/blazetest/src/mathtest/arrayslice/IncludeTest.cpp @@ -0,0 +1,61 @@ +//================================================================================================= +/*! +// \file src/mathtest/arrayslice/IncludeTest.cpp +// \brief Source file for the PageSlice include test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + return EXIT_SUCCESS; +} +//************************************************************************************************* From 7b851e86879b66c272b3f341027d4e81c25cdadd Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 31 May 2019 12:43:50 -0500 Subject: [PATCH 05/14] Adding CustomArray --- blaze_tensor/math/Array.h | 24 +- blaze_tensor/math/CustomArray.h | 154 + blaze_tensor/math/DenseArray.h | 2 +- blaze_tensor/math/DynamicArray.h | 13 +- blaze_tensor/math/dense/CustomArray.h | 3378 +++++++++++++++++ blaze_tensor/math/dense/DenseArray.h | 14 +- blaze_tensor/math/dense/DynamicArray.h | 165 +- blaze_tensor/math/dense/Forward.h | 2 + blaze_tensor/math/expressions/Array.h | 54 +- .../math/expressions/DArrDArrEqualExpr.h | 248 ++ .../math/expressions/DArrDArrMapExpr.h | 4 +- blaze_tensor/math/expressions/DArrNormExpr.h | 5 +- .../math/expressions/DArrReduceExpr.h | 13 +- blaze_tensor/math/views/arrayslice/Dense.h | 8 +- blaze_tensor/util/ArrayForEach.h | 73 +- .../mathtest/customarray/AlignedPaddedTest.h | 415 ++ blazetest/src/mathtest/CMakeLists.txt | 1 + .../customarray/AlignedPaddedTest1.cpp | 1291 +++++++ .../customarray/AlignedPaddedTest2.cpp | 2629 +++++++++++++ .../src/mathtest/customarray/CMakeLists.txt | 45 + .../src/mathtest/customarray/IncludeTest.cpp | 61 + 21 files changed, 8470 insertions(+), 129 deletions(-) create mode 100644 blaze_tensor/math/CustomArray.h create mode 100644 blaze_tensor/math/dense/CustomArray.h create mode 100644 blaze_tensor/math/expressions/DArrDArrEqualExpr.h create mode 100644 blazetest/blazetest/mathtest/customarray/AlignedPaddedTest.h create mode 100644 blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp create mode 100644 blazetest/src/mathtest/customarray/AlignedPaddedTest2.cpp create mode 100644 blazetest/src/mathtest/customarray/CMakeLists.txt create mode 100644 blazetest/src/mathtest/customarray/IncludeTest.cpp diff --git a/blaze_tensor/math/Array.h b/blaze_tensor/math/Array.h index 15937b4..bc7670b 100644 --- a/blaze_tensor/math/Array.h +++ b/blaze_tensor/math/Array.h @@ -41,6 +41,7 @@ // Includes //************************************************************************************************* +#include #include #include @@ -48,6 +49,7 @@ #include #include +#include namespace blaze { @@ -136,17 +138,17 @@ inline std::ostream& operator<<( std::ostream& os, const Array& m ) { CompositeType_t tmp( ~m ); -// for (size_t k = 0UL; k < tmp.pages(); ++k) { -// os << "("; -// for (size_t i = 0UL; i < tmp.rows(); ++i) { -// os << "("; -// for (size_t j = 0UL; j < tmp.columns(); ++j) { -// os << std::setw(12) << tmp(k, i, j) << " "; -// } -// os << ") "; -// } -// os << ")\n"; -// } + ArrayForEachGrouped( + tmp.dimensions(), + [&]( std::array< size_t, MT::num_dimensions() > const& dims ) { + os << std::setw( 12 ) << tmp( dims ) << " "; + }, + [&]( size_t ) { os << "("; }, + [&]( size_t i ) { + os << ")"; + if( i == 0 ) + os << "\n"; + } ); return os; } diff --git a/blaze_tensor/math/CustomArray.h b/blaze_tensor/math/CustomArray.h new file mode 100644 index 0000000..b65a7ce --- /dev/null +++ b/blaze_tensor/math/CustomArray.h @@ -0,0 +1,154 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/CustomArray.h +// \brief Header file for the complete CustomArray implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_CUSTOMARRAY_H_ +#define _BLAZE_TENSOR_MATH_CUSTOMARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + +#include + +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// RAND SPECIALIZATION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the Rand class template for CustomArray. +// \ingroup random +// +// This specialization of the Rand class creates random instances of CustomArray. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +class Rand< CustomArray > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( CustomArray& tensor ) const; + + template< typename Arg > + inline void randomize( CustomArray& tensor, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a CustomArray. +// +// \param tensor The tensor to be randomized. +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void Rand< CustomArray >::randomize( CustomArray& tensor ) const +{ + using blaze::randomize; + + ArrayForEachGrouped( + tensor.dimensions(), [&]( std::array< size_t, N > const& dims ) { + randomize( tensor( dims ) ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a CustomArray. +// +// \param tensor The tensor to be randomized. +// \param min The smallest possible value for a tensor element. +// \param max The largest possible value for a tensor element. +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Arg > // Min/max argument type +inline void Rand< CustomArray >::randomize( CustomArray& tensor, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + ArrayForEachGrouped( + tensor.dimensions(), [&]( std::array< size_t, N > const& dims ) { + randomize( tensor( dims ), min, max ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MAKE FUNCTIONS +// +//================================================================================================= + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/DenseArray.h b/blaze_tensor/math/DenseArray.h index 3147fc6..8da5247 100644 --- a/blaze_tensor/math/DenseArray.h +++ b/blaze_tensor/math/DenseArray.h @@ -119,7 +119,7 @@ #include #include // #include -// #include +#include #include // #include // #include diff --git a/blaze_tensor/math/DynamicArray.h b/blaze_tensor/math/DynamicArray.h index 417d10d..43e3aa6 100644 --- a/blaze_tensor/math/DynamicArray.h +++ b/blaze_tensor/math/DynamicArray.h @@ -160,8 +160,10 @@ inline void Rand< DynamicArray >::randomize( DynamicArray& arr { using blaze::randomize; - ArrayForEach( array.dimensions(), - [v = array.data()]( size_t i ) { randomize( v[i] ); } ); + ArrayForEachGrouped( + array.dimensions(), [&]( std::array< size_t, N > const& dims ) { + randomize( array( dims ) ); + } ); } /*! \endcond */ //************************************************************************************************* @@ -184,9 +186,10 @@ inline void Rand< DynamicArray< N, Type > >::randomize( { using blaze::randomize; - ArrayForEach( array.dimensions(), [v = array.data(), min, max]( size_t i ) { - randomize( v[i], min, max ); - } ); + ArrayForEachGrouped( + array.dimensions(), [&]( std::array< size_t, N > const& dims ) { + randomize( array( dims ), min, max ); + } ); } /*! \endcond */ //************************************************************************************************* diff --git a/blaze_tensor/math/dense/CustomArray.h b/blaze_tensor/math/dense/CustomArray.h new file mode 100644 index 0000000..7e7c5f8 --- /dev/null +++ b/blaze_tensor/math/dense/CustomArray.h @@ -0,0 +1,3378 @@ +//================================================================================================= +/*! +// \file blaze_array/math/dense/CustomArray.h +// \brief Header file for the implementation of a customizable array +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_DENSE_CUSTOMARRAY_H_ +#define _BLAZE_TENSOR_MATH_DENSE_CUSTOMARRAY_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\defgroup custom_array CustomArray +// \ingroup dense_array +*/ +/*!\brief Efficient implementation of a customizable array. +// \ingroup custom_array +// +// The CustomArray class template provides the functionality to represent an external array of +// elements of arbitrary type and a fixed size as a native \b Blaze dense array data structure. +// Thus in contrast to all other dense array types a custom array does not perform any kind +// of memory allocation by itself, but it is provided with an existing array of element during +// construction. A custom array can therefore be considered an alias to the existing array. +// +// The type of the elements, the properties of the given array of elements and the storage order +// of the array can be specified via the following four template parameters: + + \code + template< size_t N, typename T, bool AF, bool PF, typename RT > + class CustomArray; + \endcode + +// - N: dimensionality of the dense array +// - Type: specifies the type of the array elements. CustomArray can be used with any +// non-cv-qualified, non-reference, non-pointer element type. +// - AF : specifies whether the represented, external arrays are properly aligned with +// respect to the available instruction set (SSE, AVX, ...) or not. +// - PF : specified whether the represented, external arrays are properly padded with +// respect to the available instruction set (SSE, AVX, ...) or not. +// +// The following examples give an impression of several possible types of custom matrices: + + \code + using blaze::CustomArray; + using blaze::aligned; + using blaze::unaligned; + using blaze::padded; + using blaze::unpadded; + + // Definition of a 3-D custom array for unaligned, unpadded integer arrays + using UnalignedUnpadded = CustomArray<3,int,unaligned,unpadded>; + + // Definition of a custom 4-D array for unaligned but padded 'float' arrays + using UnalignedPadded = CustomArray<4,float,unaligned,padded>; + + // Definition of a custom 4-D array for aligned, unpadded 'double' arrays + using AlignedUnpadded = CustomArray<4,double,aligned,unpadded>; + + // Definition of a custom 3-D array for aligned, padded 'complex' arrays + using AlignedPadded = CustomArray<3,complex,aligned,padded>; + \endcode + +// \n \section customarray_special_properties Special Properties of Custom Matrices +// +// In comparison with the remaining \b Blaze dense array types CustomArray has several special +// characteristics. All of these result from the fact that a custom array is not performing any +// kind of memory allocation, but instead is given an existing array of elements. The following +// sections discuss all of these characteristics: +// +// -# \ref customarray_memory_management +// -# \ref customarray_copy_operations +// -# \ref customarray_alignment +// -# \ref customarray_padding +// +// \n \subsection customarray_memory_management Memory Management +// +// The CustomArray class template acts as an adaptor for an existing array of elements. As such +// it provides everything that is required to use the array just like a native \b Blaze dense +// array data structure. However, this flexibility comes with the price that the user of a custom +// array is responsible for the resource management. +// +// The following examples give an impression of several possible custom matrices: + + \code + using blaze::CustomArray; + using blaze::Deallocate; + using blaze::allocate; + using blaze::aligned; + using blaze::unaligned; + using blaze::padded; + using blaze::unpadded; + + // Definition of a 3x4 custom array with unaligned, unpadded and externally + // managed integer array. Note that the std::vector must be guaranteed to outlive the + // custom array! + std::vector vec( 12UL ); + CustomArray<2,int,unaligned,unpadded> A( &vec[0], 3UL, 4UL ); + + // Definition of a custom 8x12 array for an aligned and padded integer array of + // capacity 128 (including 8 padding elements per row). Note that the std::unique_ptr + // must be guaranteed to outlive the custom array! + std::unique_ptr memory( allocate( 128UL ) ); + CustomArray<2,int,aligned,padded> B( memory.get(), 8UL, 12UL, 16UL ); + \endcode + +// \n \subsection customarray_copy_operations Copy Operations +// +// As with all dense matrices it is possible to copy construct a custom array: + + \code + using blaze::CustomArray; + using blaze::unaligned; + using blaze::unpadded; + + using CustomType = CustomArray<2,int,unaligned,unpadded>; + + std::vector vec( 6UL, 10 ); // Vector of 6 integers of the value 10 + CustomType A( &vec[0], 2UL, 3UL ); // Represent the std::vector as Blaze dense array + a[1] = 20; // Also modifies the std::vector + + CustomType B( a ); // Creating a copy of vector a + b[2] = 20; // Also affects array A and the std::vector + \endcode + +// It is important to note that a custom array acts as a reference to the specified array. Thus +// the result of the copy constructor is a new custom array that is referencing and representing +// the same array as the original custom array. +// +// In contrast to copy construction, just as with references, copy assignment does not change +// which array is referenced by the custom matrices, but modifies the values of the array: + + \code + std::vector vec2( 6UL, 4 ); // Vector of 6 integers of the value 4 + CustomType C( &vec2[0], 2UL, 3UL ); // Represent the std::vector as Blaze dense array + + A = C; // Copy assignment: Set all values of array A and B to 4. + \endcode + +// \n \subsection customarray_alignment Alignment +// +// In case the custom array is specified as \a aligned the passed array must adhere to some +// alignment restrictions based on the alignment requirements of the used data type and the +// used instruction set (SSE, AVX, ...). The restriction applies to the first element of each +// row/column: In case of a array the first element of each row must be properly +// aligned, in case of a column-major array the first element of each column must be properly +// aligned. For instance, if a array is used and AVX is active the first element of +// each row must be 32-bit aligned: + + \code + using blaze::CustomArray; + using blaze::Deallocate; + using blaze::allocate; + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + // Allocation of 32-bit aligned memory + std::unique_ptr memory( allocate( 40UL ) ); + + CustomArray<2,int,aligned,padded> A( memory.get(), 8UL, 5UL, 6UL ); + \endcode + +// In the example, the array has six columns. However, since with AVX eight integer +// values are loaded together the array is padded with two additional elements. This guarantees +// that the first element of each row is 32-bit aligned. In case the alignment requirements are +// violated, a \a std::invalid_argument exception is thrown. +// +// \n \subsection customarray_padding Padding +// +// Adding padding elements to the end of an array can have a significant impact on performance. +// For instance, assuming that AVX is available, then two aligned, padded, 3x3 double precision +// matrices can be added via three SIMD addition operations: + + \code + using blaze::CustomArray; + using blaze::Deallocate; + using blaze::allocate; + using blaze::aligned; + using blaze::padded; + + using CustomType = CustomArray<2,double,aligned,padded>; + + std::unique_ptr memory1( allocate( 12UL ) ); + std::unique_ptr memory2( allocate( 12UL ) ); + std::unique_ptr memory3( allocate( 12UL ) ); + + // Creating padded custom 3x3 array with an additional padding element in each row + CustomType A( memory1.get(), 3UL, 3UL, 4UL ); + CustomType B( memory2.get(), 3UL, 3UL, 4UL ); + CustomType C( memory3.get(), 3UL, 3UL, 4UL ); + + // ... Initialization + + C = A + B; // AVX-based array addition + \endcode + +// In this example, maximum performance is possible. However, in case no padding elements are +// inserted a scalar addition has to be used: + + \code + using blaze::CustomArray; + using blaze::Deallocate; + using blaze::allocate; + using blaze::aligned; + using blaze::unpadded; + + using CustomType = CustomArray<2,double,aligned,unpadded>; + + std::unique_ptr memory1( allocate( 9UL ) ); + std::unique_ptr memory2( allocate( 9UL ) ); + std::unique_ptr memory3( allocate( 9UL ) ); + + // Creating unpadded custom 3x3 array + CustomType A( memory1.get(), 3UL, 3UL ); + CustomType B( memory2.get(), 3UL, 3UL ); + CustomType C( memory3.get(), 3UL, 3UL ); + + // ... Initialization + + C = A + B; // Scalar array addition + \endcode + +// Note that the construction of padded and unpadded aligned matrices looks identical. However, +// in case of padded matrices, \b Blaze will zero initialize the padding element and use them +// in all computations in order to achieve maximum performance. In case of an unpadded array +// \b Blaze will ignore the elements with the downside that it is not possible to load a complete +// row to an AVX register, which makes it necessary to fall back to a scalar addition. +// +// The number of padding elements is required to be sufficient with respect to the available +// instruction set: In case of an aligned padded custom array the added padding elements must +// guarantee that the total number of elements in each row/column is a multiple of the SIMD +// vector width. In case of an unaligned padded array the number of padding elements can be +// greater or equal the number of padding elements of an aligned padded custom array. In case +// the padding is insufficient with respect to the available instruction set, a +// \a std::invalid_argument exception is thrown. +// +// +// \n \section customarray_arithmetic_operations Arithmetic Operations +// +// The use of custom matrices in arithmetic operations is designed to be as natural and intuitive +// as possible. All operations (addition, subtraction, multiplication, scaling, ...) can be +// expressed similar to a text book representation. Also, custom matrices can be combined with all +// other dense and sparse vectors and matrices. The following example gives an impression of the +// use of CustomArray: + + \code + using blaze::CustomArray; + using blaze::CompressedArray; + using blaze::Deallocate; + using blaze::allocate; + using blaze::aligned; + using blaze::unaligned; + using blaze::padded; + using blaze::unpadded; + using blaze::rowMajor; + using blaze::columnMajor; + + // Non-initialized custom 2x3 array. All given arrays are considered to be + // unaligned and unpadded. The memory is managed via a 'std::vector'. + std::vector memory1( 6UL ); + CustomArray<2,double,unaligned,unpadded> A( memory1.data(), 2UL, 3UL ); + + A(0,0) = 1.0; A(0,1) = 2.0; A(0,2) = 3.0; // Initialization of the first row + A(1,0) = 4.0; A(1,1) = 5.0; A(1,2) = 6.0; // Initialization of the second row + + // Non-initialized custom 2x3 array with padding elements. All given arrays are + // required to be properly aligned and padded. The memory is managed via a 'std::unique_ptr'. + std::unique_ptr memory2( allocate( 16UL ) ); + CustomArray<2,double,aligned,padded> B( memory2.get(), 8UL, 2UL, 3UL ); + + B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row + B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row + + CompressedArray<2,float> C( 2, 3 ); // Empty sparse single precision array + DynamicArray<2,float> D( init_from_value, 4.0F, 3, 2 ); // Directly, homogeneously initialized single precision 3x2 array + + DynamicArray<2,double> E( A ); // Creation of a new array as a copy of A + DynamicArray<2,double> F; // Creation of a default column-major array + + E = A + B; // Array addition and assignment to a array + F = A - C; // Array subtraction and assignment to a column-major array + F = A * D; // Array multiplication between two matrices of different element types + + A *= 2.0; // In-place scaling of array A + E = 2.0 * B; // Scaling of array B + F = D * 2.0; // Scaling of array D + + E += A - B; // Addition assignment + E -= A + C; // Subtraction assignment + F *= A * D; // Multiplication assignment + \endcode +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT = DynamicArray> > // Result type +class CustomArray + : public DenseArray< CustomArray > +{ + public: + //**Type definitions**************************************************************************** + using This = CustomArray; //!< Type of this CustomArray instance. + using BaseType = DenseArray; //!< Base type of this CustomArray instance. + + //! Result type for expression template evaluations. + using ResultType = RT; + + //! Result type with opposite storage order for expression template evaluations. + using OppositeType = OppositeType_t; + + //! Transpose type for expression template evaluations. + using TransposeType = TransposeType_t; + + using ElementType = Type; //!< Type of the array elements. + using SIMDType = SIMDTrait_t; //!< SIMD type of the array elements. + using ReturnType = const Type&; //!< Return type for expression template evaluations. + using CompositeType = const This&; //!< Data type for composite expression templates. + + using Reference = Type&; //!< Reference to a non-constant array value. + using ConstReference = const Type&; //!< Reference to a constant array value. + using Pointer = Type*; //!< Pointer to a non-constant array value. + using ConstPointer = const Type*; //!< Pointer to a constant array value. + + using Iterator = DenseIterator; //!< Iterator over non-constant elements. + using ConstIterator = DenseIterator; //!< Iterator over constant elements. + //********************************************************************************************** + + //**Rebind struct definition******************************************************************** + /*!\brief Rebind mechanism to obtain a CustomArray with different data/element type. + */ + template< typename NewType > // Data type of the other array + struct Rebind { + using RRT = Rebind_t< RT, RemoveConst_t >; //!< The rebound result type. + using Other = CustomArray; //!< The type of the other CustomArray. + }; + //********************************************************************************************** + + //**Resize struct definition******************************************************************** + /*!\brief Resize mechanism to obtain a CustomArray with different fixed dimensions. + */ + template< size_t... New > // Dimensionalities of the other array + struct Resize { + using RRT = Resize_t; //!< The resized result type. + using Other = CustomArray; //!< The type of the other CustomArray. + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation flag for SIMD optimization. + /*! The \a simdEnabled compilation flag indicates whether expressions the array is involved + in can be optimized via SIMD operations. In case the element type of the array is a + vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise + it is set to \a false. */ + static constexpr bool simdEnabled = IsVectorizable_v; + + //! Compilation flag for SMP assignments. + /*! The \a smpAssignable compilation flag indicates whether the array can be used in SMP + (shared memory parallel) assignments (both on the left-hand and right-hand side of the + assignment). */ + static constexpr bool smpAssignable = !IsSMPAssignable_v; + //********************************************************************************************** + + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit inline CustomArray(); + template< typename... Dims > + explicit inline CustomArray( Type const* ptr, Dims... dims ); + + inline CustomArray( const CustomArray& m ); + inline CustomArray( CustomArray&& m ) noexcept; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~CustomArray() = default; + //@} + //********************************************************************************************** + + //**Data access functions*********************************************************************** + /*!\name Data access functions */ + //@{ + template< typename... Dims > + inline Reference operator()( Dims... dims ) noexcept; + template< typename... Dims > + inline ConstReference operator()( Dims... dims ) const noexcept; + inline Reference operator()( std::array< size_t, N > const& indices ) noexcept; + inline ConstReference operator()( std::array< size_t, N > const& indices ) const noexcept; + template< typename... Dims > + inline Reference at( Dims... dims ); + template< typename... Dims > + inline ConstReference at( Dims... dims ) const; + inline Reference at( std::array< size_t, N > const& indices ); + inline ConstReference at( std::array< size_t, N > const& indices ) const; + inline Pointer data () noexcept; + inline ConstPointer data () const noexcept; + template< typename... Dims > + inline Pointer data ( size_t i, Dims... subdims ) noexcept; + template< typename... Dims > + inline ConstPointer data ( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline Iterator begin ( size_t i, Dims... subdims ) noexcept; + template< typename... Dims > + inline ConstIterator begin ( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline ConstIterator cbegin( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline Iterator end ( size_t i, Dims... subdims ) noexcept; + template< typename... Dims > + inline ConstIterator end ( size_t i, Dims... subdims ) const noexcept; + template< typename... Dims > + inline ConstIterator cend ( size_t i, Dims... subdims ) const noexcept; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + inline CustomArray& operator=( const Type& set ); + inline CustomArray& operator=( nested_initializer_list< N, Type > list ); + + inline CustomArray& operator=( const CustomArray& rhs ); + inline CustomArray& operator=( CustomArray&& rhs ) noexcept; + + template< typename MT > inline CustomArray& operator= ( const Array& rhs ); + template< typename MT > inline CustomArray& operator+=( const Array& rhs ); + template< typename MT > inline CustomArray& operator-=( const Array& rhs ); + template< typename MT > inline CustomArray& operator%=( const Array& rhs ); + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + inline static constexpr size_t num_dimensions() noexcept { return N; } + inline constexpr std::array< size_t, N > const& dimensions() const noexcept; + template < size_t Dim > + inline size_t dimension() const noexcept; + inline size_t spacing() const noexcept; + inline size_t capacity() const noexcept; + template< typename... Dims > + inline size_t capacity( size_t i, Dims... subdims ) const noexcept; + inline size_t nonZeros() const; + template< typename... Dims > + inline size_t nonZeros( size_t i, Dims... subdims ) const; + inline void reset(); + template< typename... Dims > + inline void reset( size_t i, Dims... subdims ); + inline void clear(); + inline void swap( CustomArray& m ) noexcept; + //@} + //********************************************************************************************** + + //**Numeric functions*************************************************************************** + /*!\name Numeric functions */ + //@{ + inline CustomArray& transpose(); + inline CustomArray& ctranspose(); + template< typename T > + inline CustomArray& transpose( const T* indices, size_t n ); + template< typename T > + inline CustomArray& ctranspose( const T* indices, size_t n ); + + template< typename Other > inline CustomArray& scale( const Other& scalar ); + //@} + //********************************************************************************************** + + //**Resource management functions*************************************************************** + /*!\name Resource management functions */ + //@{ + template< typename... Dims > + inline void reset( Type* ptr, Dims... dims ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > ); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedAddAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + HasSIMDAdd_v< Type, ElementType_t > && + !IsDiagonal_v ); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedSubAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + HasSIMDSub_v< Type, ElementType_t > && + !IsDiagonal_v ); + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename MT > + static constexpr bool VectorizedSchurAssign_v = + ( useOptimizedKernels && + simdEnabled && MT::simdEnabled && + IsSIMDCombinable_v< Type, ElementType_t > && + HasSIMDMult_v< Type, ElementType_t > ); + /*! \endcond */ + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + public: + //**Expression template evaluation functions**************************************************** + /*!\name Expression template evaluation functions */ + //@{ + template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept; + template< typename Other > inline bool isAliased( const Other* alias ) const noexcept; + + inline bool isAligned () const noexcept; + inline bool canSMPAssign() const noexcept; + + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType load ( Dims... dims ) const noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType loada( Dims... dims ) const noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE SIMDType loadu( Dims... dims ) const noexcept; + + template< typename... Dims > + BLAZE_ALWAYS_INLINE void store ( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void storea( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void storeu( const SIMDType& value, Dims... dims ) noexcept; + template< typename... Dims > + BLAZE_ALWAYS_INLINE void stream( const SIMDType& value, Dims... dims ) noexcept; + + template< typename MT > + inline auto assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v >; + + template< typename MT > + inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; + + template< typename MT > + inline auto addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; + + template< typename MT > + inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; + + template< typename MT > + inline auto subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; + + template< typename MT > + inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; + + template< typename MT > + inline auto schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; + + template< typename MT > + inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; + //@} + //********************************************************************************************** + + private: + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + template< typename... Dims > + inline static std::array< size_t, N > initDimensions( Dims... dims ) noexcept; + template< typename... Dims > + inline static size_t initSpacing( Dims... dims ) noexcept; + template< typename... Dims > + inline size_t index( Dims... dims ) const noexcept; + inline size_t index( std::array< size_t, N > const& indices ) const noexcept; + template< typename... Dims > + inline size_t row_index( size_t i, Dims... subdims ) const noexcept; + //@} + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::array< size_t, N > dims_; //!< The current dimensions of the array (dims[1]...dims_[N]) . + size_t nn_; //!< The number of elements between two rows. + Type* BLAZE_RESTRICT v_; //!< The custom array of elements. + /*!< Access to the array elements is gained via the function call + operator. */ + //@} + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type ); + BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type ); + BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief The default constructor for CustomArray. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray::CustomArray() + : dims_( ) // The current dimensions of the array + , nn_( 0UL ) // The number of elements between two rows + , v_ ( nullptr ) // The custom array of elements +{} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Constructor for a array of size \f$ m \times n \f$. +// +// \param ptr The array of elements to be used by the array. +// \param m The number of rows of the array of elements. +// \param n The number of columns of the array of elements. +// \param o The number of pages of the array of elements. +// \param nn The total number of elements between two rows/columns. +// \exception std::invalid_argument Invalid setup of custom array. +// +// This constructor creates a custom array of size \f$ m \times n \f$. The construction fails +// if ... +// +// - ... the passed pointer is \c nullptr; +// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly +// aligned according to the available instruction set (SSE, AVX, ...); +// - ... the specified spacing \a nn is insufficient for the given data type \a Type and the +// available instruction set. +// +// In all failure cases a \a std::invalid_argument exception is thrown. +// +// \note The custom array does \b NOT take responsibility for the given array of elements! +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline CustomArray::CustomArray( Type const* ptr, Dims... dims ) + : dims_ ( initDimensions( dims... ) ) // The current dimensions of the array + , nn_( initSpacing( dims... ) ) // The number of elements between two rows + , v_ ( const_cast< Type* BLAZE_RESTRICT >(ptr) ) // The custom array of elements +{ + using blaze::clear; + + using ClearFunctor = If_t< PF || !IsConst_v, Clear, Noop >; + + if( ptr == nullptr ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array of elements" ); + } + + if( AF && ( !checkAlignment( ptr ) || nn_ % SIMDSIZE != 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid alignment detected" ); + } + + if( sizeof...(dims) == N + 1 ) { + if( PF && IsVectorizable_v && ( nn_ < nextMultiple( dims_[0], SIMDSIZE ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded array" ); + } + + if( PF && IsVectorizable_v ) { + ClearFunctor clear; + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { clear( v_[i] ); } ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The copy constructor for CustomArray. +// +// \param m Array to be copied. +// +// The copy constructor initializes the custom array as an exact copy of the given custom array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray::CustomArray( const CustomArray& m ) + : dims_( m.dims_ ) // The current number of pages of the array + , nn_( m.nn_ ) // The number of elements between two rows + , v_ ( m.v_ ) // The custom array of elements +{} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The move constructor for CustomArray. +// +// \param m The array to be moved into this instance. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray::CustomArray( CustomArray&& m ) noexcept + : dims_( std::move( m.dims_ ) ) // The current number of pages of the array + , nn_( m.nn_ ) // The number of elements between two rows + , v_ ( m.v_ ) // The custom array of elements +{ + m.dims_ = std::array< size_t, N >{}; + m.nn_ = 0UL; + m.v_ = nullptr; + + BLAZE_INTERNAL_ASSERT( m.data() == nullptr, "Invalid data reference detected" ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Initialize the dimensions array. +// +// \param value The dimensions for this CustomArray. +// \return The dimensions array. +// +// This function initializes the internal dimensions array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline std::array< size_t, N > CustomArray::initDimensions( Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( Dims ) || N + 1 == sizeof...( Dims ) ); + + // the last dimension could be the spacing that needs to be ignored + constexpr size_t padding_offset = sizeof...( Dims ) - N; + + // the last given dimension is always the lowest + const size_t indices[] = { dims... }; + + std::array< size_t, N > result; + for( size_t i = 0; i != N; ++i ) { + result[i] = indices[sizeof...( Dims ) - i - 1 - padding_offset]; + } + return result; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Initialize the spacing. +// +// \param value The dimensions for this CustomArray. +// \return The dimensions array. +// +// This function initializes the internal dimensions array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline size_t CustomArray::initSpacing( Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( Dims ) || N + 1 == sizeof...( Dims ) ); + + // the last given dimension is the spacing + const size_t indices[] = { dims... }; + return indices[sizeof...( Dims ) - 1]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline size_t CustomArray::row_index( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + size_t indices[] = { dims..., i, 0 }; + + size_t idx = 0UL; + for( size_t i = N - 1; i > 1; --i ) { + BLAZE_USER_ASSERT(indices[N - i - 1] < dims_[i], "Invalid access index" ); + idx = (idx + indices[N - i - 1]) * dims_[i - 1]; + } + + BLAZE_USER_ASSERT(indices[N - 2] < dims_[1], "Invalid access index" ); + BLAZE_USER_ASSERT(indices[N - 1] < dims_[0], "Invalid access index" ); + + return (idx + indices[N - 2]) * nn_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate element index. +// +// \param value The index-array for the element access. +// \return The element index. +// +// This function calculates the overall element index into the underlying memory from the ND indices +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline size_t CustomArray::index( Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + size_t indices[] = { size_t(dims)... }; + + size_t idx = 0UL; + for( size_t i = N - 1; i > 1; --i ) { + BLAZE_USER_ASSERT(indices[N - i] < dims_[i], "Invalid access index" ); + idx = (idx + indices[N - i - 1]) * dims_[i - 1]; + } + + BLAZE_USER_ASSERT(indices[N - 2] < dims_[1], "Invalid access index" ); + BLAZE_USER_ASSERT(indices[N - 1] < dims_[0], "Invalid access index" ); + + return (idx + indices[N - 2]) * nn_ + indices[N - 1]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate element index. +// +// \param value The index-array for the element access. +// \return The element index. +// +// This function calculates the overall element index into the underlying memory from the ND indices +*/ +// 3 3 2 2 1 0 0 +// ( ( ( c + 0 ) * o_ + k ) * m_ + i ) * nn_ + j +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::index( std::array< size_t, N > const& indices ) const noexcept +{ + size_t idx = 0UL; + for( size_t i = N - 1; i > 1; --i ) { + BLAZE_USER_ASSERT( indices[i] < dims_[i], "Invalid access index" ); + idx = (idx + indices[i]) * dims_[i - 1]; + } + + BLAZE_USER_ASSERT(indices[1] < dims_[1], "Invalid access index" ); + BLAZE_USER_ASSERT(indices[0] < dims_[0], "Invalid access index" ); + + return (idx + indices[1]) * nn_ + indices[0]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline constexpr std::array< size_t, N > const& CustomArray::dimensions() const noexcept +{ + return dims_; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// DATA ACCESS FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief 2D-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::Reference + CustomArray::operator()( Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( Dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + + return v_[index( dims... )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief 2D-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstReference + CustomArray::operator()( Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N == sizeof...( Dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + + return v_[index( dims... )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ND-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline typename CustomArray::Reference + CustomArray::operator()( std::array< size_t, N > const& indices ) noexcept +{ +#if defined(BLAZE_USER_ASSERTION) + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[i] < dim, "Invalid array access index" ); + } ); +#endif + + return v_[index( indices )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief ND-access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline typename CustomArray::ConstReference + CustomArray::operator()( std::array< size_t, N > const& indices ) const noexcept +{ +#if defined(BLAZE_USER_ASSERTION) + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[i] < dim, "Invalid array access index" ); + } ); +#endif + + size_t idx = index( indices ); + + return v_[index( indices )]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::Reference + CustomArray::at( Dims... dims ) +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[N - i - 1] >= dim ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstReference + CustomArray::at( Dims... dims ) const +{ + BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); + + size_t indices[] = { size_t(dims)... }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[N - i - 1] >= dim ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline typename CustomArray::Reference + CustomArray::at( std::array< size_t, N > const& indices ) +{ + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( indices ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checked access to the array elements. +// +// \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$. +// \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$. +// \param k Access index for the page. The index has to be in the range \f$[0..O-1]\f$. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid array access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access indices. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline typename CustomArray::ConstReference + CustomArray::at( std::array< size_t, N > const& indices ) const +{ + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + + return ( *this )( indices ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dynamic array. Note that you +// can NOT assume that all array elements lie adjacent to each other! The dynamic array may +// use techniques such as padding to improve the alignment of the data. Whereas the number of +// elements within a row/column are given by the \c rows() and \c columns() member functions, +// respectively, the total number of elements including padding is given by the \c spacing() +// member function. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline typename CustomArray::Pointer + CustomArray::data() noexcept +{ + return v_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dynamic array. Note that you +// can NOT assume that all array elements lie adjacent to each other! The dynamic array may +// use techniques such as padding to improve the alignment of the data. Whereas the number of +// elements within a row/column are given by the \c rows() and \c columns() member functions, +// respectively, the total number of elements including padding is given by the \c spacing() +// member function. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline typename CustomArray::ConstPointer + CustomArray::data() const noexcept +{ + return v_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements of row/column \a i. +// +// \param i The row/column index. +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage for the elements in row/column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::Pointer + CustomArray::data( size_t i, Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return v_ + row_index( i, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Low-level data access to the array elements of row/column \a i. +// +// \param i The row/column index. +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage for the elements in row/column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstPointer + CustomArray::data( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return v_ + row_index( i, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// +// \param i The row/column index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the storage order is set to \a rowMajor the function returns an iterator to the first element +// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator +// to the first element of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::Iterator + CustomArray::begin( size_t i, Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return Iterator( v_ + row_index( i, dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// +// \param i The row/column index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the storage order is set to \a rowMajor the function returns an iterator to the first element +// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator +// to the first element of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstIterator + CustomArray::begin( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator to the first element of row/column \a i. +// +// \param i The row/column index. +// \return Iterator to the first element of row/column \a i. +// +// This function returns a row/column iterator to the first element of row/column \a i. In case +// the storage order is set to \a rowMajor the function returns an iterator to the first element +// of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator +// to the first element of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstIterator + CustomArray::cbegin( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// +// \param i The row/column index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the storage order is set to \a rowMajor the function returns an iterator just past +// the last element of row \a i, in case the storage flag is set to \a columnMajor the function +// returns an iterator just past the last element of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::Iterator + CustomArray::end( size_t i, Dims... dims ) noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return Iterator( v_ + row_index( i, dims... ) + dims_[0] ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// +// \param i The row/column index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the storage order is set to \a rowMajor the function returns an iterator just past +// the last element of row \a i, in case the storage flag is set to \a columnMajor the function +// returns an iterator just past the last element of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstIterator + CustomArray::end( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) + dims_[0] ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns an iterator just past the last element of row/column \a i. +// +// \param i The row/column index. +// \return Iterator just past the last element of row/column \a i. +// +// This function returns an row/column iterator just past the last element of row/column \a i. +// In case the storage order is set to \a rowMajor the function returns an iterator just past +// the last element of row \a i, in case the storage flag is set to \a columnMajor the function +// returns an iterator just past the last element of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline typename CustomArray::ConstIterator + CustomArray::cend( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); + + return ConstIterator( v_ + row_index( i, dims... ) + dims_[0] ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ASSIGNMENT OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Homogeneous assignment to all array elements. +// +// \param rhs Scalar value to be assigned to all array elements. +// \return Reference to the assigned array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray& + CustomArray::operator=( const Type& rhs ) +{ + ArrayForEach( dims_, nn_, [&]( size_t i ) { v_[i] = rhs; } ); + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief List assignment to all array elements. +// +// \param list The initializer list. +// \exception std::invalid_argument Invalid assignment to static array. +// +// This assignment operator offers the option to directly assign to all elements of the array +// by means of an initializer list: + + \code + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + const int array[9] = { 0, 0, 0, + 0, 0, 0, + 0, 0, 0 }; + blaze::CustomArray A( array, 3UL, 3UL ); + A = { { 1, 2, 3 }, + { 4, 5 }, + { 7, 8, 9 } }; + \endcode + +// The array elements are assigned the values from the given initializer list. Missing values +// are initialized as default (as e.g. the value 6 in the example). Note that in case the size +// of the top-level initializer list exceeds the number of rows or the size of any nested list +// exceeds the number of columns, a \a std::invalid_argument exception is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray& + CustomArray::operator=( nested_initializer_list< N, Type > list ) +{ + auto list_dims = list.dimensions(); + if( ArrayDimAnyOf( dims_, + [&]( size_t i, size_t dim ) { return list_dims[i] != dim; } ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to custom array" ); + } + + list.transfer_data( *this ); + + if( IsVectorizable_v ) { + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { v_[i] = Type(); } ); + } + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Copy assignment operator for CustomArray. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +// \exception std::invalid_argument Array sizes do not match. +// +// The array is initialized as a copy of the given array. In case the current sizes of the two +// matrices don't match, a \a std::invalid_argument exception is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray& + CustomArray::operator=( const CustomArray& rhs ) +{ + auto rhsdims = rhs.dimensions(); + if( ArrayDimAnyOf( dims_, + [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + smpAssign( *this, ~rhs ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Move assignment operator for CustomArray. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray& + CustomArray::operator=( CustomArray&& rhs ) noexcept +{ + dims_ = std::move( rhs.dims_ ); // The current dimensions of the array + nn_ = rhs.nn_; // The number of elements between two rows + v_ = rhs.v_; // The custom array of elements + + rhs.dims_ = std::array< size_t, N >{}; + rhs.nn_ = 0UL; + rhs.v_ = nullptr; + + BLAZE_INTERNAL_ASSERT( rhs.data() == nullptr, "Invalid data reference detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Assignment operator for different matrices. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +// \exception std::invalid_argument Array sizes do not match. +// +// The array is initialized as a copy of the given array. In case the current sizes of the two +// matrices don't match, a \a std::invalid_argument exception is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side array +inline CustomArray& + CustomArray::operator=( const Array& rhs ) +{ + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, tmp ); + } + else { + smpAssign( *this, ~rhs ); + } + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Addition assignment operator for the addition of a array (\f$ A+=B \f$). +// +// \param rhs The right-hand side array to be added to the array. +// \return Reference to the array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side array +inline CustomArray& + CustomArray::operator+=( const Array& rhs ) +{ + auto rhsdims = (~rhs).dimensions(); + if( ArrayDimAnyOf( dims_, + [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAddAssign( *this, tmp ); + } + else { + smpAddAssign( *this, ~rhs ); + } + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Subtraction assignment operator for the subtraction of a array (\f$ A-=B \f$). +// +// \param rhs The right-hand side array to be subtracted from the array. +// \return Reference to the array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side array +inline CustomArray& + CustomArray::operator-=( const Array& rhs ) +{ + auto rhsdims = (~rhs).dimensions(); + if( ArrayDimAnyOf( dims_, + [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSubAssign( *this, tmp ); + } + else { + smpSubAssign( *this, ~rhs ); + } + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Schur product assignment operator for the multiplication of a array (\f$ A\circ=B \f$). +// +// \param rhs The right-hand side array for the Schur product. +// \return Reference to the array. +// \exception std::invalid_argument Array sizes do not match. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side array +inline CustomArray& + CustomArray::operator%=( const Array& rhs ) +{ + auto rhsdims = (~rhs).dimensions(); + if( ArrayDimAnyOf( dims_, + [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSchurAssign( *this, tmp ); + } + else { + smpSchurAssign( *this, ~rhs ); + } + + return *this; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Returns the current number of elements in the given dimension of the array. +// +// \return The number of cubes of the array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template < size_t Dim > +inline size_t CustomArray::dimension() const noexcept +{ + BLAZE_STATIC_ASSERT( Dim < N ); + + return dims_[Dim]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the spacing between the beginning of two rows/columns. +// +// \return The spacing between the beginning of two rows/columns. +// +// This function returns the spacing between the beginning of two rows/columns, i.e. the +// total number of elements of a row/column. In case the storage order is set to \a rowMajor +// the function returns the spacing between two rows, in case the storage flag is set to +// \a columnMajor the function returns the spacing between two columns. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::spacing() const noexcept +{ + return nn_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the maximum capacity of the array. +// +// \return The capacity of the array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::capacity() const noexcept +{ + size_t capacity = nn_; + for( size_t i = 1; i < N; ++i ) { + capacity *= dims_[i]; + } + return capacity; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the current capacity of the specified row/column. +// +// \param i The index of the row/column. +// \return The current capacity of row/column \a i. +// +// This function returns the current capacity of the specified row/column. In case the +// storage order is set to \a rowMajor the function returns the capacity of row \a i, +// in case the storage flag is set to \a columnMajor the function returns the capacity +// of column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline size_t CustomArray::capacity( size_t i, Dims... dims ) const noexcept +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( Dims ) ); + + MAYBE_UNUSED( dims... ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)..., i, 0 }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + + return nn_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the total number of non-zero elements in the array +// +// \return The number of non-zero elements in the dense array. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::nonZeros() const +{ + size_t nonzeros( 0UL ); + + ArrayForEach( dims_, nn_, [&]( size_t i ) { + if( !isDefault( v_[i] ) ) { + ++nonzeros; + } + } ); + + return nonzeros; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the number of non-zero elements in the specified row/column. +// +// \param i The index of the row/column. +// \return The number of non-zero elements of row/column \a i. +// +// This function returns the current number of non-zero elements in the specified row/column. +// In case the storage order is set to \a rowMajor the function returns the number of non-zero +// elements in row \a i, in case the storage flag is set to \a columnMajor the function returns +// the number of non-zero elements in column \a i. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline size_t CustomArray::nonZeros( size_t i, Dims... dims ) const +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( Dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)..., i, 0 }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + + const size_t jstart = row_index( i, dims... ); + const size_t jend = jstart + dims_[0]; + size_t nonzeros( 0UL ); + + for( size_t j = jstart; j < jend; ++j ) + if( !isDefault( v_[j] ) ) + ++nonzeros; + + return nonzeros; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reset to the default initial values. +// +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void CustomArray::reset() +{ + using blaze::clear; + ArrayForEach( dims_, nn_, [&]( size_t i ) { clear( v_[i] ); } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reset the specified row/column to the default initial values. +// +// \param i The index of the row/column. +// \return void +// +// This function resets the values in the specified row/column to their default value. In case +// the storage order is set to \a rowMajor the function resets the values in row \a i, in case +// the storage order is set to \a columnMajor the function resets the values in column \a i. +// Note that the capacity of the row/column remains unchanged. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline void CustomArray::reset( size_t i, Dims... dims ) +{ + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( Dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)..., i, 0 }; + + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + + using blaze::clear; + + size_t row_elements = row_index( i, dims... ); + + for( size_t j = 0UL; j < dims_[0]; ++j ) + clear( v_[row_elements + j] ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Clearing the \f$ M \times N \f$ array. +// +// \return void +// +// After the clear() function, the size of the array is 0. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void CustomArray::clear() +{ + dims_ = std::array< size_t, N >{}; + nn_ = 0UL; + v_ = nullptr; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Swapping the contents of two matrices. +// +// \param m The array to be swapped. +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void CustomArray::swap( CustomArray& m ) noexcept +{ + using std::swap; + + swap( dims_ , m.dims_ ); + swap( nn_, m.nn_ ); + swap( v_ , m.v_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// NUMERIC FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief In-place transpose of the array. +// +// \return Reference to the transposed array. +// \exception std::logic_error Impossible transpose operation. +// +// In case the array is not a square array, a \a std::logic_error exception is thrown. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline CustomArray& CustomArray::transpose() +{ +// using std::swap; +// +// if( o_ != m_ || m_ != n_ ) { +// BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); +// } +// +// for( size_t i=1UL; i // Result type +template< typename T > // Type of the mapping indices +inline CustomArray& CustomArray::transpose( const T* indices, size_t n ) +{ +// using std::swap; +// +// if( o_ != m_ || m_ != n_ ) { +// BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); +// } +// +// for( size_t i=1UL; i // Result type +inline CustomArray& CustomArray::ctranspose() +{ +// if( o_ != m_ || m_ != n_ ) { +// BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); +// } +// +// for( size_t i=0UL; i // Result type +template< typename T > // Type of the mapping indices +inline CustomArray& CustomArray::ctranspose( const T* indices, size_t n ) +{ +// if( o_ != m_ || m_ != n_ ) { +// BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); +// } +// +// for( size_t i=0UL; i A( ... ); + + A *= 4; // Scaling of the array + A.scale( 4 ); // Same effect as above + \endcode +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other > // Data type of the scalar value +inline CustomArray& CustomArray::scale( const Other& scalar ) +{ + ArrayForEach( dims_, nn_, [&]( size_t i ) { v_[i] *= scalar; } ); + return *this; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// RESOURCE MANAGEMENT FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Resets the custom array and replaces the array of elements with the given array. +// +// \param ptr The array of elements to be used by the array. +// \param m The number of rows of the array of elements. +// \param n The number of columns of the array of elements. +// \return void +// \exception std::invalid_argument Invalid setup of custom array. +// +// This function resets the custom array to the given array of elements of size \f$ m \times n \f$. +// The function fails if ... +// +// - ... the passed pointer is \c nullptr; +// - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly +// aligned according to the available instruction set (SSE, AVX, ...). +// +// In all failure cases a \a std::invalid_argument exception is thrown. +// +// \note This function is \b NOT available for padded custom matrices! +// \note In case a deleter was specified, the previously referenced array will only be destroyed +// when the last custom array referencing the array goes out of scope. +// \note The custom array does NOT take responsibility for the new array of elements! +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +inline void CustomArray::reset( Type* ptr, Dims... dims ) +{ + BLAZE_STATIC_ASSERT( N == sizeof...( Dims ) || N + 1 == sizeof...( Dims ) ); + BLAZE_STATIC_ASSERT( PF == unpadded || N + 1 == sizeof...( Dims ) ); + + CustomArray tmp( ptr, dims... ); + swap( tmp ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TEMPLATE EVALUATION FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Returns whether the array can alias with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this array, \a false if not. +// +// This function returns whether the given address can alias with the array. In contrast +// to the isAliased() function this function is allowed to use compile time expressions +// to optimize the evaluation. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other > // Data type of the foreign expression +inline bool CustomArray::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( alias ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the array is aliased with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this array, \a false if not. +// +// This function returns whether the given address is aliased with the array. In contrast +// to the canAlias() function this function is not allowed to use compile time expressions +// to optimize the evaluation. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other > // Data type of the foreign expression +inline bool CustomArray::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( alias ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the array is properly aligned in memory. +// +// \return \a true in case the array is aligned, \a false if not. +// +// This function returns whether the array is guaranteed to be properly aligned in memory, i.e. +// whether the beginning and the end of each row/column of the array are guaranteed to conform +// to the alignment restrictions of the element type \a Type. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline bool CustomArray::isAligned() const noexcept +{ + return ( AF || ( checkAlignment( v_ ) && dimension<0>() % SIMDSIZE == 0UL ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the array can be used in SMP assignments. +// +// \return \a true in case the array can be used in SMP assignments, \a false if not. +// +// This function returns whether the array can be used in SMP assignments. In contrast to the +// \a smpAssignable member enumeration, which is based solely on compile time information, this +// function additionally provides runtime information (as for instance the current number of +// rows and/or columns of the array). +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline bool CustomArray::canSMPAssign() const noexcept +{ + return ( capacity() >= SMP_DMATASSIGN_THRESHOLD ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Load of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \return The loaded SIMD element. +// +// This function performs a load of a specific SIMD element of the dense array. The row index +// must be smaller than the number of rows and the column index must be smaller then the number +// of columns. Additionally, the column index (in case of a array) or the row index +// (in case of a column-major array) must be a multiple of the number of values inside the +// SIMD element. This function must \b NOT be called explicitly! It is used internally for the +// performance optimized evaluation of expression templates. Calling this function explicitly +// might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename CustomArray::SIMDType + CustomArray::load( Dims... dims ) const noexcept +{ + if( AF && PF ) + return loada( dims... ); + else + return loadu( dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Aligned load of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \return The loaded SIMD element. +// +// This function performs an aligned load of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename CustomArray::SIMDType + CustomArray::loada( Dims... dims ) const noexcept +{ + using blaze::loada; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( !PF || j % SIMDSIZE == 0UL, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); + + return loada( v_ + index( dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Unaligned load of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \return The loaded SIMD element. +// +// This function performs an unaligned load of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE typename CustomArray::SIMDType + CustomArray::loadu( Dims... dims ) const noexcept +{ + using blaze::loadu; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" ); + + return loadu( v_ + index( dims... ) ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs a store of a specific SIMD element of the dense array. The row index +// must be smaller than the number of rows and the column index must be smaller than the number +// of columns. Additionally, the column index (in case of a array) or the row index +// (in case of a column-major array) must be a multiple of the number of values inside the +// SIMD element. This function must \b NOT be called explicitly! It is used internally for the +// performance optimized evaluation of expression templates. Calling this function explicitly +// might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + CustomArray::store( const SIMDType& value, Dims... dims ) noexcept +{ + if( AF && PF ) + storea( value, dims... ); + else + storeu( value, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Aligned store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned store of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + CustomArray::storea( const SIMDType& value, Dims... dims ) noexcept +{ + using blaze::storea; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( !PF || j % SIMDSIZE == 0UL, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); + + storea( v_ + index( dims... ), value ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Unaligned store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an unaligned store of a specific SIMD element of the dense array. +// The row index must be smaller than the number of rows and the column index must be smaller +// than the number of columns. Additionally, the column index (in case of a array) +// or the row index (in case of a column-major array) must be a multiple of the number of +// values inside the SIMD element. This function must \b NOT be called explicitly! It is used +// internally for the performance optimized evaluation of expression templates. Calling this +// function explicitly might result in erroneous results and/or in compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + CustomArray::storeu( const SIMDType& value, Dims... dims ) noexcept +{ + using blaze::storeu; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" ); + + storeu( v_ + index( dims... ), value ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Aligned, non-temporal store of a SIMD element of the array. +// +// \param i Access index for the row. The index has to be in the range [0..M-1]. +// \param j Access index for the column. The index has to be in the range [0..N-1]. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned, non-temporal store of a specific SIMD element of the +// dense array. The row index must be smaller than the number of rows and the column index +// must be smaller than the number of columns. Additionally, the column index (in case of a +// array) or the row index (in case of a column-major array) must be a multiple +// of the number of values inside the SIMD element. This function must \b NOT be called +// explicitly! It is used internally for the performance optimized evaluation of expression +// templates. Calling this function explicitly might result in erroneous results and/or in +// compilation errors. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename... Dims > +BLAZE_ALWAYS_INLINE void + CustomArray::stream( const SIMDType& value, Dims... dims ) noexcept +{ + using blaze::stream; + + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= ( PF ? nn_ : n_ ), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( !PF || j % SIMDSIZE == 0UL, "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); + + stream( v_ + index( dims... ), value ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Default implementation of the assignment of a dense array. +// +// \param rhs The right-hand side dense array to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::assign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + + const size_t jpos( dims_[0] & size_t(-2) ); + BLAZE_INTERNAL_ASSERT( ( dims_[0] - ( dims_[0] % 2UL ) ) == jpos, "Invalid end calculation" ); + + ArrayForEachGrouped( + dims_, nn_, [&]( size_t i, std::array< size_t, N > const& dims ) { + v_[i] = ( ~rhs )( dims ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief SIMD optimized implementation of the assignment of a dense array. +// +// \param rhs The right-hand side dense array to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::assign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + +// constexpr bool remainder( !PF || !IsPadded_v ); +// +// const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) ); +// BLAZE_INTERNAL_ASSERT( !remainder || ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); +// +// if( AF && PF && useStreaming && +// ( m_*n_*o_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) ) +// { +// for (size_t k=0UL; k right((~rhs).begin(i, k)); +// +// for (; j right((~rhs).begin(i, k)); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::addAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedAddAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + + const size_t jpos( dims_[0] & size_t(-2) ); + BLAZE_INTERNAL_ASSERT( ( dims_[0] - ( dims_[0] % 2UL ) ) == jpos, "Invalid end calculation" ); + + ArrayForEachGrouped( + dims_, nn_, [&]( size_t i, std::array< size_t, N > const& dims ) { + v_[i] += ( ~rhs )( dims ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief SIMD optimized implementation of the addition assignment of a dense array. +// +// \param rhs The right-hand side dense array to be added. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::addAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedAddAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + +// constexpr bool remainder( !PF || !IsPadded_v ); +// +// for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::subAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedSubAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + + const size_t jpos( dims_[0] & size_t(-2) ); + BLAZE_INTERNAL_ASSERT( ( dims_[0] - ( dims_[0] % 2UL ) ) == jpos, "Invalid end calculation" ); + + ArrayForEachGrouped( + dims_, nn_, [&]( size_t i, std::array< size_t, N > const& dims ) { + v_[i] -= ( ~rhs )( dims ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief SIMD optimized implementation of the subtraction assignment of a dense array. +// +// \param rhs The right-hand side dense array to be subtracted. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::subAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedSubAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + +// constexpr bool remainder( !PF || !IsPadded_v ); +// +// for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::schurAssign( const DenseArray& rhs ) + -> DisableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + + const size_t jpos( dims_[0] & size_t(-2) ); + BLAZE_INTERNAL_ASSERT( ( dims_[0] - ( dims_[0] % 2UL ) ) == jpos, "Invalid end calculation" ); + + ArrayForEachGrouped( + dims_, nn_, [&]( size_t i, std::array< size_t, N > const& dims ) { + v_[i] *= ( ~rhs )( dims ); + } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief SIMD optimized implementation of the Schur product assignment of a dense array. +// +// \param rhs The right-hand side dense array for the Schur product. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename MT > // Type of the right-hand side dense array +inline auto CustomArray::schurAssign( const DenseArray& rhs ) + -> EnableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); + +// constexpr bool remainder( !PF || !IsPadded_v ); +// +// for (size_t k=0UL; k right((~rhs).begin(i, k)); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Result type +inline void reset( CustomArray& m ); + +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT // Result type + , typename... Dims > // indices of row +inline void reset( CustomArray& m, size_t i, Dims... dims ); + +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void clear( CustomArray& m ); + +template< bool RF // Relaxation flag + , size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline bool isDefault( const CustomArray& m ); + +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline bool isIntact( const CustomArray& m ); + +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void swap( CustomArray& a, CustomArray& b ) noexcept; +//@} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Resetting the given custom array. +// \ingroup custom_array +// +// \param m The array to reset. +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void reset( CustomArray& m ) +{ + m.reset(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reset the specified row/column of the given custom array. +// \ingroup custom_array +// +// \param m The array to reset. +// \param i The index of the row/column to reset. +// \param k The index of the page to reset. +// \return void +// +// This function resets the values in the specified row/column of the given custom array to +// their default value. In case the given array is a \a rowMajor array the function resets the +// values in row \a i, if it is a \a columnMajor array the function resets the values in column +// \a i. Note that the capacity of the row/column remains unchanged. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT // Result type + , typename... Dims > // indices of row +inline void reset( CustomArray& m, size_t i, Dims... dims ) +{ + m.reset( i, dims... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Clearing the given custom array. +// \ingroup custom_array +// +// \param m The array to be cleared. +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void clear( CustomArray& m ) +{ + m.clear(); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the given custom array is in default state. +// \ingroup custom_array +// +// \param m The array to be tested for its default state. +// \return \a true in case the given array's rows and columns are zero, \a false otherwise. +// +// This function checks whether the custom array is in default (constructed) state, i.e. if +// it's number of rows and columns is 0. In case it is in default state, the function returns +// \a true, else it will return \a false. The following example demonstrates the use of the +// \a isDefault() function: + + \code + using blaze::aligned; + using blaze::padded; + + blaze::CustomArray A( ... ); + // ... Resizing and initialization + if( isDefault( A ) ) { ... } + \endcode + +// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed +// semantics (blaze::relaxed): + + \code + if( isDefault( A ) ) { ... } + \endcode +*/ +template< bool RF // Relaxation flag + , size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline bool isDefault( const CustomArray& m ) +{ + return ArrayDimAllOf( + m.dimensions(), []( size_t, size_t dim ) { return dim == 0UL; } ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns whether the invariants of the given custom array are intact. +// \ingroup custom_array +// +// \param m The custom array to be tested. +// \return \a true in case the given array's invariants are intact, \a false otherwise. +// +// This function checks whether the invariants of the custom array are intact, i.e. if its +// state is valid. In case the invariants are intact, the function returns \a true, else it +// will return \a false. The following example demonstrates the use of the \a isIntact() +// function: + + \code + using blaze::aligned; + using blaze::padded; + + blaze::CustomArray A( ... ); + // ... Resizing and initialization + if( isIntact( A ) ) { ... } + \endcode +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline bool isIntact( const CustomArray& m ) +{ + size_t capacity = m.spacing(); + for( size_t i = 1; i < N; ++i ) { + capacity *= m.dimensions()[i]; + } + return ( capacity <= m.capacity() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Swapping the contents of two custom matrices. +// \ingroup custom_array +// +// \param a The first array to be swapped. +// \param b The second array to be swapped. +// \return void +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline void swap( CustomArray& a, CustomArray& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename T, bool AF, bool PF, typename RT > +struct HasConstDataAccess< CustomArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename T, bool AF, bool PF, typename RT > +struct HasMutableDataAccess< CustomArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCUSTOM SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename T, bool AF, bool PF, typename RT > +struct IsCustom< CustomArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename T, bool PF, typename RT > +struct IsAligned< CustomArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCONTIGUOUS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename T, bool AF, bool PF, typename RT > +struct IsContiguous< CustomArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t N, typename T, bool AF, typename RT > +struct IsPadded< CustomArray > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/dense/DenseArray.h b/blaze_tensor/math/dense/DenseArray.h index 1fe3e24..1504f44 100644 --- a/blaze_tensor/math/dense/DenseArray.h +++ b/blaze_tensor/math/dense/DenseArray.h @@ -64,7 +64,7 @@ #include // #include -// #include +#include #include // #include // #include @@ -477,8 +477,8 @@ bool isUniform_backend( const DenseArray& dm ) BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT ); #if defined(BLAZE_INTERNAL_ASSERTION) - ArrayDimForEach( ( ~dm ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims_[i] != 0, "Invalid array dimension detected" ); + ArrayDimForEach( ( ~dm ).dimensions(), [&]( size_t, size_t dim ) { + BLAZE_INTERNAL_ASSERT( dim != 0, "Invalid array dimension detected" ); } ); #endif @@ -535,10 +535,10 @@ template< bool RF // Relaxation flag bool isUniform( const DenseArray& dm ) { if( IsUniform_v< MT > || - ArrayDimAnyOf( - ( ~dm ).dimensions(), []( size_t i ) { return i == 0; } ) || - ArrayDimAllOf( - ( ~dm ).dimensions(), []( size_t i ) { return i == 1; } ) ) { + ArrayDimAnyOf( ( ~dm ).dimensions(), + []( size_t, size_t dim ) { return dim == 0; } ) || + ArrayDimAllOf( ( ~dm ).dimensions(), + []( size_t, size_t dim ) { return dim == 1; } ) ) { return true; } diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index e650b9c..f5b5834 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -197,14 +197,14 @@ class DynamicArray /*!\name Constructors */ //@{ explicit inline DynamicArray() noexcept; - template< typename... Dims > + template< typename... Dims, typename = EnableIf_t< sizeof...(Dims) == N - 1 > > explicit inline DynamicArray( size_t dim0, Dims... dims ); explicit inline DynamicArray( std::array< size_t, N> const& dims ); template< typename... Dims > explicit inline DynamicArray( InitFromValue, const Type& init, Dims... dims ); explicit inline DynamicArray( nested_initializer_list< N, Type > list ); - template< typename Other, typename... Dims > + template< typename Other, typename... Dims, typename = EnableIf_t< sizeof...(Dims) == N > > explicit inline DynamicArray( const Other* array, Dims... dims ); inline DynamicArray( const DynamicArray& m ); @@ -434,7 +434,6 @@ class DynamicArray //@{ template< typename... Dims > inline static std::array< size_t, N > initDimensions( Dims... dims ) noexcept; - inline static std::array< size_t, N > initDimensions( const std::array< size_t, N >& dims ) noexcept; inline static size_t addPadding( size_t value ) noexcept; inline size_t calcCapacity() const noexcept; template< typename... Dims > @@ -500,7 +499,7 @@ inline DynamicArray::DynamicArray() noexcept */ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array -template< typename... Dims > +template< typename... Dims, typename Enable > inline DynamicArray< N, Type >::DynamicArray( size_t dim0, Dims... dims ) : dims_ ( initDimensions( dim0, dims... ) ) // The current dimensions of the array , nn_ ( addPadding( dims_[0] ) ) // The length of a padded row @@ -535,7 +534,7 @@ inline DynamicArray::DynamicArray( InitFromValue, const Type& init, Dim { BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); - ArrayForEach( dims_, [&]( size_t i ) { v_[i] = init; } ); + ArrayForEach( dims_, nn_, [&]( size_t i ) { v_[i] = init; } ); BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); } @@ -602,7 +601,7 @@ inline DynamicArray::DynamicArray( nested_initializer_list< N, Type > l */ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array -template< typename Other, typename... Dims > // Data type of the initialization array +template< typename Other, typename... Dims, typename Enable > // Data type of the initialization array inline DynamicArray::DynamicArray( const Other* array, Dims... dims ) : DynamicArray( dims... ) { @@ -635,10 +634,10 @@ inline DynamicArray::DynamicArray( const Other* array, Dims... dims ) template< size_t N // The dimensionality of the array , typename Type > // Data type of the array inline DynamicArray::DynamicArray( const DynamicArray& m ) - : dims_ ( m.dims_ ) // The current dimensions of the array - , nn_ ( m.nn_ ) // The length of a padded row + : dims_ ( m.dims_ ) // The current dimensions of the array + , nn_ ( m.nn_ ) // The length of a padded row , capacity_( m.capacity_ ) // The maximum capacity of the array - , v_( allocate< Type >( capacity_ ) ) // The array elements + , v_( allocate< Type >( capacity_ ) ) // The array elements { smpAssign( *this, m ); @@ -675,10 +674,16 @@ inline DynamicArray::DynamicArray( DynamicArray&& m ) noexcept template< size_t N // The dimensionality of the array , typename Type > // Data type of the array template< typename MT > // Type of the foreign array -inline DynamicArray::DynamicArray( const Array& m ) - : DynamicArray( (~m).dimensions() ) +inline DynamicArray::DynamicArray( const Array& rhs ) + : DynamicArray( (~rhs).dimensions() ) { - smpAssign( *this, ~m ); + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, tmp ); + } + else { + smpAssign( *this, ~rhs ); + } BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); } @@ -693,7 +698,7 @@ inline DynamicArray::DynamicArray( const Array& m ) template< size_t N // The dimensionality of the array , typename Type > // Data type of the array inline DynamicArray::DynamicArray( const std::array& dims ) - : dims_( initDimensions( dims ) ) // The current dimensions of the array + : dims_ ( dims ) // The current dimensions of the array , nn_ ( addPadding( dims_[0] ) ) // The length of a padded row , capacity_( calcCapacity() ) // The maximum capacity of the array , v_( allocate< Type >( capacity_ ) ) // The array elements @@ -756,8 +761,8 @@ inline typename DynamicArray::Reference #if defined(BLAZE_USER_ASSERTION) size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dims_, [&]( size_t i ) { - BLAZE_USER_ASSERT( indices[N - i - 1] < dims_[i], "Invalid array access index" ); + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); #endif @@ -788,8 +793,8 @@ inline typename DynamicArray::ConstReference #if defined(BLAZE_USER_ASSERTION) size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dims_, [&]( size_t i ) { - BLAZE_USER_ASSERT( indices[N - i - 1] < dims_[i], "Invalid array access index" ); + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); #endif @@ -815,8 +820,8 @@ inline typename DynamicArray::Reference DynamicArray::operator()( std::array< size_t, N > const& indices ) noexcept { #if defined(BLAZE_USER_ASSERTION) - ArrayDimForEach( dims_, [&]( size_t i ) { - BLAZE_USER_ASSERT( indices[i] < dims_[i], "Invalid array access index" ); + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[i] < dim, "Invalid array access index" ); } ); #endif @@ -842,8 +847,8 @@ inline typename DynamicArray::ConstReference DynamicArray::operator()( std::array< size_t, N > const& indices ) const noexcept { #if defined(BLAZE_USER_ASSERTION) - ArrayDimForEach( dims_, [&]( size_t i ) { - BLAZE_USER_ASSERT( indices[i] < dims_[i], "Invalid array access index" ); + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[i] < dim, "Invalid array access index" ); } ); #endif @@ -874,8 +879,8 @@ inline typename DynamicArray::Reference size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dims_, [&]( size_t i ) { - if( indices[N - i - 1] >= dims_[i] ) { + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[N - i - 1] >= dim ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); @@ -907,8 +912,8 @@ inline typename DynamicArray::ConstReference size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dims_, [&]( size_t i ) { - if( indices[N - i - 1] >= dims_[i] ) { + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[N - i - 1] >= dim ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); @@ -935,8 +940,8 @@ template< size_t N // The dimensionality of the array inline typename DynamicArray::Reference DynamicArray::at( std::array< size_t, N > const& indices ) { - ArrayDimForEach( dims_, [&]( size_t i ) { - if( indices[i] >= dims_[i] ) { + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); @@ -963,8 +968,8 @@ template< size_t N // The dimensionality of the array inline typename DynamicArray::ConstReference DynamicArray::at( std::array< size_t, N > const& indices ) const { - ArrayDimForEach( dims_, [&]( size_t i ) { - if( indices[i] >= dims_[i] ) { + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); @@ -1230,7 +1235,7 @@ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array inline DynamicArray& DynamicArray::operator=(const Type& rhs) { - ArrayForEach( dims_, [&]( size_t i ) { v_[i] = rhs; } ); + ArrayForEach( dims_, nn_, [&]( size_t i ) { v_[i] = rhs; } ); return *this; } @@ -1267,6 +1272,10 @@ inline DynamicArray& list.transfer_data( *this ); + if( IsVectorizable_v ) { + ArrayForEachPadded( dims_, nn_, [&]( size_t i ) { v_[i] = Type(); } ); + } + return *this; } //************************************************************************************************* @@ -1528,6 +1537,15 @@ template< size_t N // The dimensionality of the array template< typename... Dims > inline size_t DynamicArray::capacity( size_t i, Dims... dims ) const noexcept { + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( Dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)..., i, 0 }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + MAYBE_UNUSED( dims... ); BLAZE_USER_ASSERT( i < dimension<1>(), "Invalid row access index" ); @@ -1548,7 +1566,7 @@ inline size_t DynamicArray::nonZeros() const { size_t nonzeros( 0UL ); - ArrayForEach( dims_, [&]( size_t i ) { + ArrayForEach( dims_, nn_, [&]( size_t i ) { if( !isDefault( v_[i] ) ) { ++nonzeros; } @@ -1572,6 +1590,15 @@ template< size_t N // The dimensionality of the array template< typename... Dims > inline size_t DynamicArray::nonZeros( size_t i, Dims... dims ) const { + BLAZE_STATIC_ASSERT( N - 2 == sizeof...( Dims ) ); + +#if defined(BLAZE_USER_ASSERTION) + size_t indices[] = { size_t(dims)..., i, 0 }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif + const size_t jstart = row_index( i, dims... ); const size_t jend = jstart + dims_[0]; size_t nonzeros( 0UL ); @@ -1594,7 +1621,8 @@ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array inline void DynamicArray::reset() { - ArrayForEach( dims_, [&]( size_t i ) { blaze::clear( v_[i] ); } ); + using blaze::clear; + ArrayForEach( dims_, nn_, [&]( size_t i ) { clear( v_[i] ); } ); } //************************************************************************************************* @@ -1690,7 +1718,7 @@ void DynamicArray::resize( std::array< size_t, N > const& dims, bool pr // return if no change is requested if( ArrayDimAllOf( - dims_, [&]( size_t i ) { return dims_[i] == dims[i]; } ) ) { + dims_, [&]( size_t i, size_t dim ) { return dim == dims[i]; } ) ) { return; } @@ -1763,7 +1791,7 @@ inline void DynamicArray::extend( std::array< size_t, N > const& dims, std::array< size_t, N > newdims; ArrayDimForEach( - dims_, [&]( size_t i ) { newdims[i] = dims_[i] + dims[i]; } ); + dims_, [&]( size_t i, size_t dim ) { newdims[i] = dim + dims[i]; } ); resize( newdims, preserve ); } //************************************************************************************************* @@ -1867,7 +1895,7 @@ inline size_t DynamicArray::addPadding( size_t value ) noexcept //************************************************************************************************* -/*!\briefInitialize the dimensions array. +/*!\brief Initialize the dimensions array. // // \param value The dimensions for this DynamicArray. // \return The dimensions array. @@ -1893,23 +1921,6 @@ inline std::array< size_t, N > DynamicArray::initDimensions( Dims... di //************************************************************************************************* -//************************************************************************************************* -/*!\briefInitialize the dimensions array. -// -// \param value The dimensions for this DynamicArray. -// \return The dimensions array. -// -// This function initializes the internal dimensions array. -*/ -template< size_t N // The dimensionality of the array - , typename Type > // Data type of the array -inline std::array< size_t , N > DynamicArray< N, Type >::initDimensions( const std::array< size_t, N >& dims ) noexcept -{ - return dims; -} -//************************************************************************************************* - - //************************************************************************************************* /*!\brief Calculate the capacity for the array. // @@ -2200,7 +2211,7 @@ template< size_t N // The dimensionality of the array template< typename Other > // Data type of the scalar value inline DynamicArray& DynamicArray::scale( const Other& scalar ) { - ArrayForEach( dims_, [&]( size_t i ) { v_[i] += scalar; } ); + ArrayForEach( dims_, nn_, [&]( size_t i ) { v_[i] *= scalar; } ); return *this; } //************************************************************************************************* @@ -2383,6 +2394,12 @@ BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims ) ), "Invalid alignment detected" ); @@ -2417,6 +2434,12 @@ BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); return loadu( v_ + index( dims... ) ); @@ -2480,6 +2503,12 @@ BLAZE_ALWAYS_INLINE void BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); @@ -2515,6 +2544,12 @@ BLAZE_ALWAYS_INLINE void BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); storeu( v_ + index( dims... ), value ); @@ -2549,6 +2584,12 @@ BLAZE_ALWAYS_INLINE void BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +#if defined(BLAZE_INTERNAL_ASSERTION) + size_t indices[] = { size_t(dims)... }; + ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); + } ); +#endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( checkAlignment( v_ + index( dims... ) ), "Invalid alignment detected" ); @@ -2575,7 +2616,7 @@ template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v > { - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); const size_t jpos( dims_[0] & size_t(-2) ); BLAZE_INTERNAL_ASSERT( ( dims_[0] - ( dims_[0] % 2UL ) ) == jpos, "Invalid end calculation" ); @@ -2607,7 +2648,7 @@ inline auto DynamicArray::assign( const DenseArray& rhs ) { BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); constexpr bool remainder( !usePadding || !IsPadded_v ); @@ -2676,7 +2717,7 @@ template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v > { - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); // for (size_t k=0UL; k::addAssign( const DenseArray& rhs ) { BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); constexpr bool remainder( !usePadding || !IsPadded_v ); @@ -2771,7 +2812,7 @@ template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v > { - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); // for (size_t k=0UL; k::subAssign( const DenseArray& rhs ) { BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); constexpr bool remainder( !usePadding || !IsPadded_v ); @@ -2867,7 +2908,7 @@ template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v > { - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); // const size_t jpos( n_ & size_t(-2) ); // BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" ); @@ -2907,7 +2948,7 @@ inline auto DynamicArray::schurAssign( const DenseArray& rhs ) { BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); constexpr bool remainder( !usePadding || !IsPadded_v ); @@ -3068,7 +3109,7 @@ template< bool RF // Relaxation flag inline bool isDefault( const DynamicArray& m ) { auto const& dims = m.dimensions(); - return ArrayDimAllOf( dims, [&]( size_t i ) { return dims[i] == 0; } ); + return ArrayDimAllOf( dims, [&]( size_t, size_t dim ) { return dim == 0; } ); } //************************************************************************************************* diff --git a/blaze_tensor/math/dense/Forward.h b/blaze_tensor/math/dense/Forward.h index 90b7f29..63df591 100644 --- a/blaze_tensor/math/dense/Forward.h +++ b/blaze_tensor/math/dense/Forward.h @@ -52,6 +52,8 @@ namespace blaze { // //================================================================================================= +template< size_t, typename, bool, bool, typename > class CustomArray; +template< size_t, typename > class DynamicArray; template< typename, bool, bool, typename > class CustomTensor; template< typename > class DynamicTensor; template< typename, size_t, size_t, size_t > class StaticTensor; diff --git a/blaze_tensor/math/expressions/Array.h b/blaze_tensor/math/expressions/Array.h index a339482..0d4ef17 100644 --- a/blaze_tensor/math/expressions/Array.h +++ b/blaze_tensor/math/expressions/Array.h @@ -191,8 +191,8 @@ BLAZE_ALWAYS_INLINE bool trySet( const Array& arr, std::array< size_t, N > c { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& arrdims = ( ~arr ).dimensions(); - ArrayDimForEach( arrdims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + ArrayDimForEach( arrdims, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -228,8 +228,8 @@ BLAZE_ALWAYS_INLINE bool tryAdd( const Array& arr, std::array< size_t, N > c { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& arrdims = ( ~arr ).dimensions(); - ArrayDimForEach( arrdims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + ArrayDimForEach( arrdims, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -265,8 +265,8 @@ BLAZE_ALWAYS_INLINE bool trySub( const Array& arr, std::array< size_t, N > c { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& arrdims = ( ~arr ).dimensions(); - ArrayDimForEach( arrdims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + ArrayDimForEach( arrdims, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -302,8 +302,8 @@ BLAZE_ALWAYS_INLINE bool tryMult( const Array& arr, std::array< size_t, N > { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& arrdims = ( ~arr ).dimensions(); - ArrayDimForEach( arrdims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + ArrayDimForEach( arrdims, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -380,8 +380,8 @@ BLAZE_ALWAYS_INLINE bool tryDiv( const Array& arr, std::array< size_t, N > c { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& arrdims = ( ~arr ).dimensions(); - ArrayDimForEach( arrdims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < arrdims[i], "Invalid array access index" ); + ArrayDimForEach( arrdims, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -424,8 +424,8 @@ BLAZE_ALWAYS_INLINE bool BLAZE_STATIC_ASSERT( M == N ); #if defined(BLAZE_INTERNAL_ASSERTION) - ArrayDimForEach( dims, [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( currdims[i] < dims[i], "Invalid array access index" ); + ArrayDimForEach( dims, [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( currdims[i] < dim, "Invalid array access index" ); } ); #endif @@ -461,8 +461,9 @@ BLAZE_ALWAYS_INLINE bool tryAssign( const Array& lhs, const Array& rhs, { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); - ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( rhsdims[i] != dim, "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -498,8 +499,9 @@ BLAZE_ALWAYS_INLINE bool tryAddAssign( const Array& lhs, const Array& { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); - ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( rhsdims[i] != dim, "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -535,8 +537,9 @@ BLAZE_ALWAYS_INLINE bool trySubAssign( const Array& lhs, const Array& { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); - ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( rhsdims[i] != dim, "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -573,8 +576,9 @@ BLAZE_ALWAYS_INLINE bool tryMultAssign( const Array& lhs, const Array& { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); - ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( rhsdims[i] != dim, "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -610,8 +614,9 @@ BLAZE_ALWAYS_INLINE bool trySchurAssign( const Array& lhs, const Array { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); - ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( rhsdims[i] != dim, "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif @@ -647,8 +652,9 @@ BLAZE_ALWAYS_INLINE bool tryDivAssign( const Array& lhs, const Array& { #if defined(BLAZE_INTERNAL_ASSERTION) auto const& rhsdims = ( ~rhs ).dimensions(); - ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i ) { - BLAZE_INTERNAL_ASSERT( dims[i] < rhsdims[i], "Invalid array access index" ); + ArrayDimForEach( ( ~lhs ).dimensions(), [&]( size_t i, size_t dim ) { + BLAZE_INTERNAL_ASSERT( rhsdims[i] != dim, "Invalid array access index" ); + BLAZE_INTERNAL_ASSERT( dims[i] < dim, "Invalid array access index" ); } ); #endif diff --git a/blaze_tensor/math/expressions/DArrDArrEqualExpr.h b/blaze_tensor/math/expressions/DArrDArrEqualExpr.h new file mode 100644 index 0000000..b2b644e --- /dev/null +++ b/blaze_tensor/math/expressions/DArrDArrEqualExpr.h @@ -0,0 +1,248 @@ +//================================================================================================= +/*! +// \file blaze_array/math/expressions/DArrDArrEqualExpr.h +// \brief Header file for the dense array/dense array equality comparison expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRDARREQUALEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRDARREQUALEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the dense array/dense array equality comparison. +// \ingroup dense_array +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +struct DArrDArrEqualExprHelper +{ + //**Type definitions**************************************************************************** + //! Composite type of the left-hand side dense array expression. + using CT1 = RemoveReference_t< CompositeType_t >; + + //! Composite type of the right-hand side dense array expression. + using CT2 = RemoveReference_t< CompositeType_t >; + //********************************************************************************************** + + //********************************************************************************************** + static constexpr bool value = + ( useOptimizedKernels && + CT1::simdEnabled && + CT2::simdEnabled && + HasSIMDEqual_v< ElementType_t, ElementType_t > ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL BINARY RELATIONAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default equality check of two row-major dense arrays. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array for the comparison. +// \param rhs The right-hand side dense array for the comparison. +// \return \a true if the two arrays are equal, \a false if not. +// +// Equal function for the comparison of two dense arrays. Due to the limited machine accuracy, +// a direct comparison of two floating point numbers should be avoided. This function offers the +// possibility to compare two floating-point arrays with a certain accuracy margin. +*/ +template< bool RF // Relaxation flag + , typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline bool //DisableIf_t< DArrDArrEqualExprHelper::value, bool > + equal( const DenseArray& lhs, const DenseArray& rhs ) +{ + using CT1 = CompositeType_t; + using CT2 = CompositeType_t; + + // Early exit in case the array sizes don't match + if( ( ~lhs ).dimensions() != ( ~rhs ).dimensions() ) { + return false; + } + + constexpr size_t N = MT1::num_dimensions(); + + // Evaluation of the two dense array operands + CT1 A( ~lhs ); + CT2 B( ~rhs ); + + // In order to compare the two arrays, the data values of the lower-order data + // type are converted to the higher-order data type within the equal function. + return ArrayForEachGroupedAllOf( + ( ~lhs ).dimensions(), [&]( std::array< size_t, N > const& dims ) { + return equal( A( dims ), B( dims ) ); + } ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief SIMD optimized equality check of two row-major dense arrays. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array for the comparison. +// \param rhs The right-hand side dense array for the comparison. +// \return \a true if the two arrays are equal, \a false if not. +// +// Equal function for the comparison of two dense arrays. Due to the limited machine accuracy, +// a direct comparison of two floating point numbers should be avoided. This function offers the +// possibility to compare two floating-point arrays with a certain accuracy margin. +*/ +// template< bool RF // Relaxation flag +// , typename MT1 // Type of the left-hand side dense array +// , typename MT2 > // Type of the right-hand side dense array +// inline EnableIf_t< DArrDArrEqualExprHelper::value, bool > +// equal( const DenseArray& lhs, const DenseArray& rhs ) +// { +// using CT1 = CompositeType_t; +// using CT2 = CompositeType_t; +// using XT1 = RemoveReference_t; +// using XT2 = RemoveReference_t; +// +// // Early exit in case the array sizes don't match +// auto const& rhsdims = ( ~rhs ).dimensions(); +// if( ArrayDimAnyOf( ( ~lhs ).dimensions(), +// [&]( size_t i, size_t dim ) { return dim != rhsdims[i]; } ) ) { +// return false; +// } +// +// // Evaluation of the two dense array operands +// CT1 A( ~lhs ); +// CT2 B( ~rhs ); +// +// constexpr size_t SIMDSIZE = SIMDTrait< ElementType_t >::size; +// constexpr bool remainder( !usePadding || !IsPadded_v || !IsPadded_v ); +// +// const size_t M( A.rows() ); +// const size_t N( A.columns() ); +// const size_t O( A.pages() ); +// +// const size_t jpos( ( remainder )?( N & size_t(-SIMDSIZE) ):( N ) ); +// BLAZE_INTERNAL_ASSERT( !remainder || ( N - ( N % SIMDSIZE ) ) == jpos, "Invalid end calculation" ); +// +// for (size_t k=0UL; k // Type of the right-hand side dense array +inline bool operator==( const DenseArray& lhs, const DenseArray& rhs ) +{ + return equal( lhs, rhs ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Inequality operator for the comparison of two dense arrays. +// \ingroup dense_array +// +// \param lhs The left-hand side dense array for the comparison. +// \param rhs The right-hand side dense array for the comparison. +// \return \a true if the two arrays are not equal, \a false if they are equal. +*/ +template< typename MT1 // Type of the left-hand side dense array + , typename MT2 > // Type of the right-hand side dense array +inline bool operator!=( const DenseArray& lhs, const DenseArray& rhs ) +{ + return !equal( lhs, rhs ); +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/expressions/DArrDArrMapExpr.h b/blaze_tensor/math/expressions/DArrDArrMapExpr.h index 9adc98d..aee07a4 100644 --- a/blaze_tensor/math/expressions/DArrDArrMapExpr.h +++ b/blaze_tensor/math/expressions/DArrDArrMapExpr.h @@ -462,8 +462,8 @@ class DArrDArrMapExpr inline ReturnType at( Dims... dims ) const { constexpr size_t indices[] = {dims...}; - ArrayDimForEach( lhs_.dimensions(), [&]( size_t i ) { - if( indices[i] >= lhs_.dimensions()[i] ) { + ArrayDimForEach( lhs_.dimensions(), [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); diff --git a/blaze_tensor/math/expressions/DArrNormExpr.h b/blaze_tensor/math/expressions/DArrNormExpr.h index ae450b4..5d3bbee 100644 --- a/blaze_tensor/math/expressions/DArrNormExpr.h +++ b/blaze_tensor/math/expressions/DArrNormExpr.h @@ -166,7 +166,10 @@ decltype(auto) norm_backend( const DenseArray& dm, Abs abs, Power power, Roo using ET = ElementType_t; using RT = decltype( evaluate( root( std::declval() ) ) ); - if( ArrayDimAnyOf( ( ~dm ).dimensions(), []( size_t i ) { return i == 0; } ) ) return RT{}; + if( ArrayDimAnyOf( ( ~dm ).dimensions(), + []( size_t i, size_t dim ) { return dim == 0; } ) ) { + return RT{}; + } CT tmp( ~dm ); diff --git a/blaze_tensor/math/expressions/DArrReduceExpr.h b/blaze_tensor/math/expressions/DArrReduceExpr.h index 0956c63..f72e570 100644 --- a/blaze_tensor/math/expressions/DArrReduceExpr.h +++ b/blaze_tensor/math/expressions/DArrReduceExpr.h @@ -455,8 +455,8 @@ class ReducedArray inline ReturnType at( Dims... dims ) const { constexpr size_t indices[] = {dims...}; - ArrayDimForEach( dm_.dimensions(), [&]( size_t i ) { - if( indices[i] >= dm_.dimensions()[i] ) { + ArrayDimForEach( dm_.dimensions(), [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); } } ); @@ -949,8 +949,13 @@ inline ElementType_t darrayreduce( const DenseArray& dm, OP op ) std::array< size_t, N > dims{}; - if( ArrayDimAnyOf( ( ~dm ).dimensions(), []( size_t i ) { return i == 0; } ) ) return ET{}; - if( ArrayDimAllOf( ( ~dm ).dimensions(), []( size_t i ) { return i == 1; } ) ) return ( ~dm )( dims ); + if( ArrayDimAnyOf( ( ~dm ).dimensions(), + []( size_t, size_t dim ) { return dim == 0; } ) ) + return ET{}; + + if( ArrayDimAllOf( ( ~dm ).dimensions(), + []( size_t, size_t dim ) { return dim == 1; } ) ) + return ( ~dm )( dims ); CT tmp( ~dm ); diff --git a/blaze_tensor/math/views/arrayslice/Dense.h b/blaze_tensor/math/views/arrayslice/Dense.h index 7178501..b0ffb8a 100644 --- a/blaze_tensor/math/views/arrayslice/Dense.h +++ b/blaze_tensor/math/views/arrayslice/Dense.h @@ -556,8 +556,8 @@ inline typename ArraySlice::Reference ArraySlice::at( Dims... dims ) { size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dimensions(), [&]( size_t i ) { - if( indices[N - i - 1] >= dimensions()[i] ) { + ArrayDimForEach( dimensions(), [&]( size_t i, size_t dim ) { + if( indices[N - i - 1] >= dim ) { BLAZE_THROW_OUT_OF_RANGE("Invalid array access index"); } } ); @@ -587,8 +587,8 @@ inline typename ArraySlice::ConstReference ArraySlice::at( Dims... dims) const { size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dimensions(), [&]( size_t i ) { - if( indices[N - i - 1] >= dimensions()[i] ) { + ArrayDimForEach( dimensions(), [&]( size_t i, size_t dim ) { + if( indices[N - i - 1] >= dim ) { BLAZE_THROW_OUT_OF_RANGE("Invalid array access index"); } } ); diff --git a/blaze_tensor/util/ArrayForEach.h b/blaze_tensor/util/ArrayForEach.h index 5a7d144..afedd8a 100644 --- a/blaze_tensor/util/ArrayForEach.h +++ b/blaze_tensor/util/ArrayForEach.h @@ -104,21 +104,30 @@ std::array< size_t, N + 1 > mergeDims( std::array< size_t, N > const& dims, size // template< typename F > void ArrayForEach( - std::array< size_t, 1 > const& dims, F const& f, size_t base = 0 ) + size_t dim0, F const& f, size_t base = 0 ) { - for( size_t i = 0; i != dims[0]; ++i ) { + for( size_t i = 0; i != dim0; ++i ) { f( i + base ); } } +template< typename F > +void ArrayForEach( + std::array< size_t, 2 > const& dims, size_t nn, F const& f, size_t base = 0 ) +{ + for( size_t i = base * nn, j = 0; j != dims[1]; i += nn, ++j) { + ArrayForEach( dims[0], f, i ); + } +} + template< size_t N, typename F > void ArrayForEach( - std::array< size_t, N > const& dims, F const& f, size_t base = 0 ) + std::array< size_t, N > const& dims, size_t nn, F const& f, size_t base = 0 ) { BLAZE_STATIC_ASSERT( N >= 2 ); std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); for( size_t i = base * dims[N - 2], j = 0; j != dims[N - 1]; i += dims[N - 2], ++j) { - ArrayForEach( shifted_dims, f, i ); + ArrayForEach( shifted_dims, nn, f, i ); } } //************************************************************************************************* @@ -222,6 +231,54 @@ void ArrayForEachGrouped( } //************************************************************************************************* +//************************************************************************************************* +/*!\brief ArrayForEachGrouped function to iterate over arbitrary dimension data. +// \ingroup util +*/ +template< typename F, typename F1, typename F2, size_t M > +void ArrayForEachGrouped( + size_t dim0, F const& f, F1 const& f1, F2 const& f2, std::array< size_t, M >& currdims ) +{ + f1( 0 ); + for( currdims[0] = 0; currdims[0] != dim0; ++currdims[0] ) { + f( currdims ); + } + f2( 0 ); +} + +template< typename F, typename F1, typename F2, size_t M > +void ArrayForEachGrouped( + std::array< size_t, 2 > const& dims, F const& f, F1 const& f1, F2 const& f2, std::array< size_t, M >& currdims ) +{ + f1( 1 ); + for( currdims[1] = 0; currdims[1] != dims[1]; ++currdims[1] ) { + ArrayForEachGrouped( dims[0], f, f1, f2, currdims ); + } + f2( 1 ); +} + +template< size_t N, typename F, typename F1, typename F2, size_t M > +void ArrayForEachGrouped( + std::array< size_t, N > const& dims, F const& f, F1 const& f1, F2 const& f2, std::array< size_t, M >& currdims ) +{ + BLAZE_STATIC_ASSERT( N > 2 ); + f1( N - 1 ); + std::array< size_t, N - 1 > shifted_dims = shiftDims( dims ); + for( currdims[N - 1] = 0; currdims[N - 1] != dims[N - 1]; ++currdims[N - 1] ) { + ArrayForEachGrouped( shifted_dims, f, f1, f2, currdims ); + } + f2( N - 1 ); +} + +template< size_t N, typename F, typename F1, typename F2 > +void ArrayForEachGrouped( + std::array< size_t, N > const& dims, F const& f, F1 const& f1, F2 const& f2 ) +{ + std::array< size_t, N > currdims{}; + ArrayForEachGrouped( dims, f, f1, f2, currdims ); +} +//************************************************************************************************* + //************************************************************************************************* /*!\brief ArrayForEachGrouped function to iterate over arbitrary dimension data. // \ingroup util @@ -415,7 +472,7 @@ template< size_t N, typename F > void ArrayDimForEach( std::array< size_t, N > const& dims, F const& f) { for( size_t i = 0; i < N; ++i ) { - f(i); + f( i, dims[i] ); } } //************************************************************************************************* @@ -429,7 +486,7 @@ template< size_t N, typename F > bool ArrayDimAnyOf( std::array< size_t, N > const& dims, F const& f) { for( size_t i = 0; i < N; ++i ) { - if( f( dims[i] ) ) { + if( f( i, dims[i] ) ) { return true; } } @@ -446,7 +503,7 @@ template< size_t N, typename F > bool ArrayDimAllOf( std::array< size_t, N > const& dims, F const& f) { for( size_t i = 0; i < N; ++i ) { - if( !f( dims[i] ) ) { + if( !f( i, dims[i] ) ) { return false; } } @@ -463,7 +520,7 @@ template< size_t N, typename F > bool ArrayDimNoneOf( std::array< size_t, N > const& dims, F const& f) { for( size_t i = 0; i < N; ++i ) { - if( f( dims[i] ) ) { + if( f( i, dims[i] ) ) { return false; } } diff --git a/blazetest/blazetest/mathtest/customarray/AlignedPaddedTest.h b/blazetest/blazetest/mathtest/customarray/AlignedPaddedTest.h new file mode 100644 index 0000000..50fde4a --- /dev/null +++ b/blazetest/blazetest/mathtest/customarray/AlignedPaddedTest.h @@ -0,0 +1,415 @@ +//================================================================================================= +/*! +// \file blazetest/mathtest/customarray/AlignedPaddedTest.h +// \brief Header file for the aligned/padded CustomArray class test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZETEST_MATHTEST_CUSTOMARRAY_ALIGNEDPADDEDTEST_H_ +#define _BLAZETEST_MATHTEST_CUSTOMARRAY_ALIGNEDPADDEDTEST_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace blazetest { + +namespace mathtest { + +namespace customarray { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Auxiliary class for all tests of the aligned/padded CustomArray class template. +// +// This class represents a test suite for the specialization of the blaze::CustomArray class +// template for aligned and padded custom matrices. It performs a series of both compile time +// as well as runtime tests. +*/ +class AlignedPaddedTest +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit AlignedPaddedTest(); + // No explicitly declared copy constructor. + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + // No explicitly declared destructor. + //********************************************************************************************** + + private: + //**Test functions****************************************************************************** + /*!\name Test functions */ + //@{ + void testConstructors(); + void testAssignment (); + void testAddAssign (); + void testSubAssign (); + void testSchurAssign (); + void testMultAssign (); + void testScaling (); + void testFunctionCall(); + void testAt (); + void testIterator (); + void testNonZeros (); + void testReset (); + void testClear (); + void testSwap (); + void testTranspose (); + void testCTranspose (); + void testIsDefault (); + + template< typename Type > + void checkRows( const Type& tensor, size_t expectedRows ) const; + + template< typename Type > + void checkColumns( const Type& tensor, size_t expectedColumns ) const; + + template< typename Type > + void checkPages( const Type& tensor, size_t expectedPages ) const; + + template< typename Type > + void checkCapacity( const Type& tensor, size_t minCapacity ) const; + + template< typename Type > + void checkNonZeros( const Type& tensor, size_t expectedNonZeros ) const; + + template< typename Type > + void checkNonZeros( const Type& tensor, size_t i, size_t k, size_t expectedNonZeros ) const; + //@} + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::string test_; //!< Label of the currently performed test. + //@} + //********************************************************************************************** + + //**Type definitions**************************************************************************** + //! Type of the row-major custom tensor. + using MT = blaze::CustomArray<3,int,blaze::aligned,blaze::padded>; + + using RMT = MT::Rebind::Other; //!< Rebound row-major custom tensor type. + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT::ResultType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT::OppositeType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT::TransposeType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RMT ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RMT::ResultType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RMT::OppositeType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( RMT::TransposeType ); + + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT::ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT::OppositeType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( MT::TransposeType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RMT::ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RMT::OppositeType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( RMT::TransposeType ); + + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( MT::ElementType, MT::ResultType::ElementType ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( MT::ElementType, MT::OppositeType::ElementType ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( MT::ElementType, MT::TransposeType::ElementType ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( RMT::ElementType, RMT::ResultType::ElementType ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( RMT::ElementType, RMT::OppositeType::ElementType ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( RMT::ElementType, RMT::TransposeType::ElementType ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Checking the number of rows of the given custom tensor. +// +// \param tensor The custom tensor to be checked. +// \param expectedRows The expected number of rows of the custom tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of rows of the given custom tensor. In case the actual number +// of rows does not correspond to the given expected number of rows, a \a std::runtime_error +// exception is thrown. +*/ +template< typename Type > // Type of the custom tensor +void AlignedPaddedTest::checkRows( const Type& tensor, size_t expectedRows ) const +{ + if( tensor.template dimension<1>() != expectedRows ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of rows detected\n" + << " Details:\n" + << " Number of rows : " << tensor.template dimension<1>() << "\n" + << " Expected number of rows: " << expectedRows << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of columns of the given custom tensor. +// +// \param tensor The custom tensor to be checked. +// \param expectedRows The expected number of columns of the custom tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of columns of the given custom tensor. In case the +// actual number of columns does not correspond to the given expected number of columns, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the custom tensor +void AlignedPaddedTest::checkColumns( const Type& tensor, size_t expectedColumns ) const +{ + if( tensor.template dimension<0>() != expectedColumns ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of columns detected\n" + << " Details:\n" + << " Number of columns : " << tensor.template dimension<0>() << "\n" + << " Expected number of columns: " << expectedColumns << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of pages of the given dynamic tensor. +// +// \param tensor The dynamic tensor to be checked. +// \param expectedPages The expected number of columns of the dynamic tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of pages of the given dynamic tensor. In case the +// actual number of pages does not correspond to the given expected number of pages, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic tensor +void AlignedPaddedTest::checkPages( const Type& tensor, size_t expectedPages ) const +{ + if( tensor.template dimension<2>() != expectedPages ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of pages detected\n" + << " Details:\n" + << " Number of pages : " << tensor.template dimension<2>() << "\n" + << " Expected number of pages: " << expectedPages << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the capacity of the given custom tensor. +// +// \param tensor The custom tensor to be checked. +// \param minCapacity The expected minimum capacity of the custom tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the capacity of the given custom tensor. In case the actual capacity +// is smaller than the given expected minimum capacity, a \a std::runtime_error exception is +// thrown. +*/ +template< typename Type > // Type of the custom tensor +void AlignedPaddedTest::checkCapacity( const Type& tensor, size_t minCapacity ) const +{ + if( capacity( tensor ) < minCapacity ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Capacity : " << capacity( tensor ) << "\n" + << " Expected minimum capacity: " << minCapacity << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements of the given custom tensor. +// +// \param tensor The custom tensor to be checked. +// \param expectedNonZeros The expected number of non-zero elements of the custom tensor. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements of the given custom tensor. In +// case the actual number of non-zero elements does not correspond to the given expected +// number, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the custom tensor +void AlignedPaddedTest::checkNonZeros( const Type& tensor, size_t expectedNonZeros ) const +{ + if( nonZeros( tensor ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements\n" + << " Details:\n" + << " Number of non-zeros : " << nonZeros( tensor ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( capacity( tensor ) < nonZeros( tensor ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( tensor ) << "\n" + << " Capacity : " << capacity( tensor ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements in a specific row/column of the given custom tensor. +// +// \param tensor The custom tensor to be checked. +// \param index The row/column to be checked. +// \param expectedNonZeros The expected number of non-zero elements in the specified row/column. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements in the specified row/column of the +// given custom tensor. In case the actual number of non-zero elements does not correspond +// to the given expected number, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the custom tensor +void AlignedPaddedTest::checkNonZeros( const Type& tensor, size_t i, size_t k, size_t expectedNonZeros ) const +{ + if( nonZeros( tensor, i, k ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements in row " << i << " page " << k << "\n" + << " Details:\n" + << " Number of non-zeros : " << nonZeros( tensor, i, k ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( capacity( tensor, i, k ) < nonZeros( tensor, i, k ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected in row " << i << " page " << k << "\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( tensor, i, k ) << "\n" + << " Capacity : " << capacity( tensor, i, k ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Testing the functionality of the aligned/padded CustomArray class template. +// +// \return void +*/ +void runTest() +{ + AlignedPaddedTest(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// MACRO DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Macro for the execution of the aligned/padded CustomArray class test. +*/ +#define RUN_CUSTOMARRAY_ALIGNED_PADDED_TEST \ + blazetest::mathtest::customarray::runTest() +/*! \endcond */ +//************************************************************************************************* + +} // namespace customarray + +} // namespace mathtest + +} // namespace blazetest + +#endif diff --git a/blazetest/src/mathtest/CMakeLists.txt b/blazetest/src/mathtest/CMakeLists.txt index 9101660..a574667 100644 --- a/blazetest/src/mathtest/CMakeLists.txt +++ b/blazetest/src/mathtest/CMakeLists.txt @@ -33,6 +33,7 @@ set(subdirs arrayslice columnslice + customarray customtensor densearray densetensor diff --git a/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp b/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp new file mode 100644 index 0000000..d25c632 --- /dev/null +++ b/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp @@ -0,0 +1,1291 @@ +//================================================================================================= +/*! +// \file src/mathtest/customarray/AlignedPaddedTest1.cpp +// \brief Source file for the aligned/padded CustomArray class test (part 1) +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace blazetest { + +namespace mathtest { + +namespace customarray { + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constructor for the CustomArray class test. +// +// \exception std::runtime_error Operation error detected. +*/ +AlignedPaddedTest::AlignedPaddedTest() +{ + testConstructors(); + testAssignment(); + testAddAssign(); + testSubAssign(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Test of the CustomArray constructors. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all constructors of the CustomArray class template. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testConstructors() +{ + //===================================================================================== + // Row-major default constructor + //===================================================================================== + + { + test_ = "Row-major CustomArray default constructor"; + + MT mat; + + checkRows ( mat, 0UL ); + checkColumns ( mat, 0UL ); + checkPages ( mat, 0UL ); + checkNonZeros( mat, 0UL ); + } + + + //===================================================================================== + // Row-major constructor ( Type*, size_t, size_t, size_t ) + //===================================================================================== + + { + test_ = "Row-major CustomArray constructor ( Type*, size_t, size_t, size_t )"; + + // Constructor a 2x3 custom tensor + { + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + } + + // Trying to construct a custom tensor with invalid array of elements + try { + MT mat( nullptr, 0UL, 0UL, 0UL, 0UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Constructing a custom tensor with a nullptr succeeded\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + + // Trying to construct a custom tensor with invalid alignment + if( blaze::AlignmentOf::value > sizeof(int) ) + { + try { + std::unique_ptr memory( blaze::allocate( 65UL ) ); + MT mat( memory.get()+1UL, 2UL, 2UL, 2UL, 16UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Constructing a custom tensor with invalid alignment succeeded\n" + << " Details:\n" + << " Result:\n" << mat << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } + + // Trying to construct a custom tensor with invalid row alignment + if( blaze::AlignmentOf::value > sizeof(int) ) + { + try { + std::unique_ptr memory( blaze::allocate( 60UL ) ); + MT mat( memory.get(), 2UL, 2UL, 2UL, 15UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Constructing a custom tensor with invalid row alignment succeeded\n" + << " Details:\n" + << " Result:\n" << mat << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } + + // Trying to construct a custom tensor with invalid padding + if( blaze::IsVectorizable::value ) + { + try { + std::unique_ptr memory( blaze::allocate( 12UL ) ); + MT mat( memory.get(), 2UL, 2UL, 2UL, 3UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Constructing a custom tensor with invalid padding succeeded\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } + } + + + //===================================================================================== + // Row-major copy constructor + //===================================================================================== + + { + test_ = "Row-major CustomArray copy constructor (0x0)"; + + MT mat1; + MT mat2( mat1 ); + + checkRows ( mat2, 0UL ); + checkColumns ( mat2, 0UL ); + checkPages ( mat2, 0UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray copy constructor (0x3x2)"; + + std::unique_ptr memory( blaze::allocate( 32UL ) ); + MT mat1( memory.get(), 2UL, 0UL, 3UL, 16UL ); + MT mat2( mat1 ); + + checkRows ( mat2, 0UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray copy constructor (2x0x2)"; + + std::unique_ptr memory( blaze::allocate( 20UL ) ); + MT mat1( memory.get(), 2UL, 2UL, 0UL, 0UL ); + MT mat2( mat1 ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 0UL ); + checkPages ( mat2, 2UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray copy constructor (2x2x0)"; + + std::unique_ptr memory( blaze::allocate( 32UL ) ); + MT mat1( memory.get(), 0UL, 2UL, 2UL, 16UL ); + MT mat2( mat1 ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 2UL ); + checkPages ( mat2, 0UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray copy constructor (2x3)"; + + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat1( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,0,2) = 3; + mat1(0,1,0) = 4; + mat1(0,1,1) = 5; + mat1(0,1,2) = 6; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,0,2) = 3; + mat1(1,1,0) = 4; + mat1(1,1,1) = 5; + mat1(1,1,2) = 6; + + MT mat2( mat1 ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Construction failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major move constructor + //===================================================================================== + + { + test_ = "Row-major CustomArray move constructor (0x0x0)"; + + MT mat1; + MT mat2( std::move( mat1 ) ); + + checkRows ( mat2, 0UL ); + checkColumns ( mat2, 0UL ); + checkPages ( mat2, 0UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray move constructor (0x3x2)"; + + std::unique_ptr memory( blaze::allocate( 32UL ) ); + MT mat1( memory.get(), 2UL, 0UL, 3UL, 16UL ); + MT mat2( std::move( mat1 ) ); + + checkRows ( mat2, 0UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray move constructor (2x0x2)"; + + std::unique_ptr memory( blaze::allocate( 20UL ) ); + MT mat1( memory.get(), 2UL, 2UL, 0UL, 0UL ); + MT mat2( std::move( mat1 ) ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 0UL ); + checkPages ( mat2, 2UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray move constructor (2x2x0)"; + + std::unique_ptr memory( blaze::allocate( 32UL ) ); + MT mat1( memory.get(), 0UL, 2UL, 2UL, 16UL ); + MT mat2( std::move( mat1 ) ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 2UL ); + checkPages ( mat2, 0UL ); + checkNonZeros( mat2, 0UL ); + } + + { + test_ = "Row-major CustomArray move constructor (2x3x2)"; + + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat1( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,0,2) = 3; + mat1(0,1,0) = 4; + mat1(0,1,1) = 5; + mat1(0,1,2) = 6; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,0,2) = 3; + mat1(1,1,0) = 4; + mat1(1,1,1) = 5; + mat1(1,1,2) = 6; + + MT mat2( std::move( mat1 ) ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Construction failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the CustomArray assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all assignment operators of the CustomArray class template. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testAssignment() +{ + //===================================================================================== + // Row-major homogeneous assignment + //===================================================================================== + + { + test_ = "Row-major CustomArray homogeneous assignment"; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 4UL, 16UL ); + mat = 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 4UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 24UL ); + checkNonZeros( mat, 0UL, 0UL, 4UL ); + checkNonZeros( mat, 1UL, 0UL, 4UL ); + checkNonZeros( mat, 2UL, 0UL, 4UL ); + checkNonZeros( mat, 0UL, 1UL, 4UL ); + checkNonZeros( mat, 1UL, 1UL, 4UL ); + checkNonZeros( mat, 2UL, 1UL, 4UL ); + + if( mat(0,0,0) != 2 || mat(0,0,1) != 2 || mat(0,0,2) != 2 || mat(0,0,3) != 2 || + mat(0,1,0) != 2 || mat(0,1,1) != 2 || mat(0,1,2) != 2 || mat(0,1,3) != 2 || + mat(0,2,0) != 2 || mat(0,2,1) != 2 || mat(0,2,2) != 2 || mat(0,2,3) != 2 || + mat(0,0,0) != 2 || mat(0,0,1) != 2 || mat(0,0,2) != 2 || mat(0,0,3) != 2 || + mat(0,1,0) != 2 || mat(0,1,1) != 2 || mat(0,1,2) != 2 || mat(0,1,3) != 2 || + mat(0,2,0) != 2 || mat(0,2,1) != 2 || mat(0,2,2) != 2 || mat(0,2,3) != 2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 2 2 2 2 )\n( 2 2 2 2 )\n( 2 2 2 2 ))\n(( 2 2 2 2 )\n( 2 2 2 2 )\n( 2 2 2 2 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major list assignment + //===================================================================================== + + { + test_ = "Row-major CustomArray initializer list assignment (complete list)"; + + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat = {{{1, 2, 3}, {4, 5, 6}}, {{1, 2, 3}, {4, 5, 6}}}; + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 12UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 3UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 3 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major StaticMatrix initializer list assignment (incomplete list)"; + + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat = {{{1}, {4, 5, 6}}, {{1}, {4, 5, 6}}}; + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 12UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(0,0,0) != 1 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 0 0 )\n( 4 5 6 ))\n(( 1 0 0 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major array assignment + //===================================================================================== + + { + test_ = "Row-major CustomArray array assignment"; + + const int array[2UL][2UL][3UL] = {{{1, 2, 3}, {4, 5, 6}}, {{1, 2, 3}, {4, 5, 6}}}; + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat = MT( &array[0][0][0], 2UL, 2UL, 3UL ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 12UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 3UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 3 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major copy assignment + //===================================================================================== + + { + test_ = "Row-major CustomArray copy assignment"; + + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat1( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,0,2) = 3; + mat1(0,1,0) = 4; + mat1(0,1,1) = 5; + mat1(0,1,2) = 6; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,0,2) = 3; + mat1(1,1,0) = 4; + mat1(1,1,1) = 5; + mat1(1,1,2) = 6; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major move assignment + //===================================================================================== + + { + test_ = "Row-major CustomArray move assignment"; + + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + MT mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,0,2) = 3; + mat1(0,1,0) = 4; + mat1(0,1,1) = 5; + mat1(0,1,2) = 6; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,0,2) = 3; + mat1(1,1,0) = 4; + mat1(1,1,1) = 5; + mat1(1,1,2) = 6; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = std::move( mat1 ); + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major dense tensor assignment + //===================================================================================== + + { + test_ = "Row-major/row-major CustomArray dense tensor assignment (mixed type)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,short,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1(0,0,0) = 1U; + mat1(0,0,1) = 2U; + mat1(0,0,2) = 3U; + mat1(0,1,0) = 4U; + mat1(0,1,1) = 5U; + mat1(0,1,2) = 6U; + mat1(1,0,0) = 1U; + mat1(1,0,1) = 2U; + mat1(1,0,2) = 3U; + mat1(1,1,0) = 4U; + mat1(1,1,1) = 5U; + mat1(1,1,2) = 6U; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,unsigned int,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1(0,0,0) = 1U; + mat1(0,0,1) = 2U; + mat1(0,0,2) = 3U; + mat1(0,1,0) = 4U; + mat1(0,1,1) = 5U; + mat1(0,1,2) = 6U; + mat1(1,0,0) = 1U; + mat1(1,0,1) = 2U; + mat1(1,0,2) = 3U; + mat1(1,1,0) = 4U; + mat1(1,1,1) = 5U; + mat1(1,1,2) = 6U; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor assignment stress test (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + const short min( randmin ); + const short max( randmax ); + + for( size_t i=0UL; i<10UL; ++i ) + { + const size_t rows ( blaze::rand( 0UL, 16UL ) ); + const size_t columns( blaze::rand( 0UL, 16UL ) ); + const size_t pages ( blaze::rand( 0UL, 16UL ) ); + const size_t spacing( blaze::nextMultiple( columns, 16UL ) ); + + using AlignedPadded = blaze::CustomArray<3,short,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( rows*spacing*pages ) ); + AlignedPadded mat1( memory1.get(), pages, rows, columns, spacing ); + randomize( mat1, min, max ); + + std::unique_ptr memory2( blaze::allocate( rows*spacing*pages ) ); + MT mat2( memory2.get(), pages, rows, columns, spacing ); + mat2 = mat1; + + if( mat1 != mat2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n" << mat1 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + using UnalignedUnpadded = blaze::CustomArray<3,int,unaligned,unpadded>; + std::unique_ptr memory1( new int[13UL] ); + UnalignedUnpadded mat1( memory1.get()+1UL, 2UL, 2UL, 3UL ); + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,0,2) = 3; + mat1(0,1,0) = 4; + mat1(0,1,1) = 5; + mat1(0,1,2) = 6; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,0,2) = 3; + mat1(1,1,0) = 4; + mat1(1,1,1) = 5; + mat1(1,1,2) = 6; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 12UL ); + checkNonZeros( mat2, 0UL, 0UL, 3UL ); + checkNonZeros( mat2, 1UL, 0UL, 3UL ); + checkNonZeros( mat2, 0UL, 1UL, 3UL ); + checkNonZeros( mat2, 1UL, 1UL, 3UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,0,2) != 3 || + mat2(0,1,0) != 4 || mat2(0,1,1) != 5 || mat2(0,1,2) != 6 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 2 || mat2(1,0,2) != 3 || + mat2(1,1,0) != 4 || mat2(1,1,1) != 5 || mat2(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor assignment stress test (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + const int min( randmin ); + const int max( randmax ); + + for( size_t i=0UL; i<10UL; ++i ) + { + const size_t rows ( blaze::rand( 0UL, 16UL ) ); + const size_t columns( blaze::rand( 0UL, 16UL ) ); + const size_t pages ( blaze::rand( 0UL, 16UL ) ); + const size_t spacing( blaze::nextMultiple( columns, 16UL ) ); + + using UnalignedUnpadded = blaze::CustomArray<3,int,unaligned,unpadded>; + std::unique_ptr memory1( new int[rows*columns*pages+1UL] ); + UnalignedUnpadded mat1( memory1.get()+1UL, pages, rows, columns ); + randomize( mat1, min, max ); + + std::unique_ptr memory2( blaze::allocate( rows*spacing*pages ) ); + MT mat2( memory2.get(), pages, rows, columns, spacing ); + mat2 = mat1; + + if( mat1 != mat2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n" << mat1 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the CustomArray addition assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the addition assignment operators of the CustomArray class +// template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testAddAssign() +{ + //===================================================================================== + // Row-major dense tensor addition assignment + //===================================================================================== + + { + test_ = "Row-major/row-major CustomArray dense tensor addition assignment (mixed type)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,short,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1 = 0; + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,1,0) = -3; + mat1(0,1,2) = 4; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,1,0) = -3; + mat1(1,1,2) = 4; + + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat2( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 += mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 8UL ); + checkNonZeros( mat2, 0UL, 0UL, 2UL ); + checkNonZeros( mat2, 1UL, 0UL, 2UL ); + checkNonZeros( mat2, 0UL, 1UL, 2UL ); + checkNonZeros( mat2, 1UL, 1UL, 2UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 0 || mat2(0,0,2) != 6 || + mat2(0,1,0) != 2 || mat2(0,1,1) != 0 || mat2(0,1,2) != 4 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 0 || mat2(1,0,2) != 6 || + mat2(1,1,0) != 2 || mat2(1,1,1) != 0 || mat2(1,1,2) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 0 6 )\n( 2 0 4 ))\n(( 1 0 6 )\n( 2 0 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor addition assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,int,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1 = 0; + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,1,0) = -3; + mat1(0,1,2) = 4; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,1,0) = -3; + mat1(1,1,2) = 4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 += mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 8UL ); + checkNonZeros( mat2, 0UL, 0UL, 2UL ); + checkNonZeros( mat2, 1UL, 0UL, 2UL ); + checkNonZeros( mat2, 0UL, 1UL, 2UL ); + checkNonZeros( mat2, 1UL, 1UL, 2UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 0 || mat2(0,0,2) != 6 || + mat2(0,1,0) != 2 || mat2(0,1,1) != 0 || mat2(0,1,2) != 4 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 0 || mat2(1,0,2) != 6 || + mat2(1,1,0) != 2 || mat2(1,1,1) != 0 || mat2(1,1,2) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 0 6 )\n( 2 0 4 ))\n(( 1 0 6 )\n( 2 0 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor addition assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + using UnalignedUnpadded = blaze::CustomArray<3,int,unaligned,unpadded>; + std::unique_ptr memory1( new int[13UL] ); + UnalignedUnpadded mat1( memory1.get()+1UL, 2UL, 2UL, 3UL ); + mat1 = 0; + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,1,0) = -3; + mat1(0,1,2) = 4; + mat1(1,0,0) = 1; + mat1(1,0,1) = 2; + mat1(1,1,0) = -3; + mat1(1,1,2) = 4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 += mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 8UL ); + checkNonZeros( mat2, 0UL, 0UL, 2UL ); + checkNonZeros( mat2, 1UL, 0UL, 2UL ); + checkNonZeros( mat2, 0UL, 1UL, 2UL ); + checkNonZeros( mat2, 1UL, 1UL, 2UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 0 || mat2(0,0,2) != 6 || + mat2(0,1,0) != 2 || mat2(0,1,1) != 0 || mat2(0,1,2) != 4 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 0 || mat2(1,0,2) != 6 || + mat2(1,1,0) != 2 || mat2(1,1,1) != 0 || mat2(1,1,2) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 0 6 )\n( 2 0 4 ))\n(( 1 0 6 )\n( 2 0 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the CustomArray subtraction assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the subtraction assignment operators of the CustomArray +// class template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testSubAssign() +{ + //===================================================================================== + // Row-major dense tensor subtraction assignment + //===================================================================================== + + { + test_ = "Row-major/row-major CustomArray dense tensor subtraction assignment (mixed type)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,short,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1 = 0; + mat1(0,0,0) = -1; + mat1(0,0,1) = -2; + mat1(0,1,0) = 3; + mat1(0,1,2) = -4; + mat1(1,0,0) = -1; + mat1(1,0,1) = -2; + mat1(1,1,0) = 3; + mat1(1,1,2) = -4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 -= mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 8UL ); + checkNonZeros( mat2, 0UL, 0UL, 2UL ); + checkNonZeros( mat2, 1UL, 0UL, 2UL ); + checkNonZeros( mat2, 0UL, 1UL, 2UL ); + checkNonZeros( mat2, 1UL, 1UL, 2UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 0 || mat2(0,0,2) != 6 || + mat2(0,1,0) != 2 || mat2(0,1,1) != 0 || mat2(0,1,2) != 4 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 0 || mat2(1,0,2) != 6 || + mat2(1,1,0) != 2 || mat2(1,1,1) != 0 || mat2(1,1,2) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 0 6 )\n( 2 0 4 ))\n(( 1 0 6 )\n( 2 0 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor subtraction assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,int,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1 = 0; + mat1(0,0,0) = -1; + mat1(0,0,1) = -2; + mat1(0,1,0) = 3; + mat1(0,1,2) = -4; + mat1(1,0,0) = -1; + mat1(1,0,1) = -2; + mat1(1,1,0) = 3; + mat1(1,1,2) = -4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 -= mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 8UL ); + checkNonZeros( mat2, 0UL, 0UL, 2UL ); + checkNonZeros( mat2, 1UL, 0UL, 2UL ); + checkNonZeros( mat2, 0UL, 1UL, 2UL ); + checkNonZeros( mat2, 1UL, 1UL, 2UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 0 || mat2(0,0,2) != 6 || + mat2(0,1,0) != 2 || mat2(0,1,1) != 0 || mat2(0,1,2) != 4 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 0 || mat2(1,0,2) != 6 || + mat2(1,1,0) != 2 || mat2(1,1,1) != 0 || mat2(1,1,2) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 0 6 )\n( 2 0 4 ))\n(( 1 0 6 )\n( 2 0 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor subtraction assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + using UnalignedUnpadded = blaze::CustomArray<3,int,unaligned,unpadded>; + std::unique_ptr memory1( new int[13UL] ); + UnalignedUnpadded mat1( memory1.get()+1UL, 2UL, 2UL, 3UL ); + mat1 = 0; + mat1(0,0,0) = -1; + mat1(0,0,1) = -2; + mat1(0,1,0) = 3; + mat1(0,1,2) = -4; + mat1(1,0,0) = -1; + mat1(1,0,1) = -2; + mat1(1,1,0) = 3; + mat1(1,1,2) = -4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 -= mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 8UL ); + checkNonZeros( mat2, 0UL, 0UL, 2UL ); + checkNonZeros( mat2, 1UL, 0UL, 2UL ); + checkNonZeros( mat2, 0UL, 1UL, 2UL ); + checkNonZeros( mat2, 1UL, 1UL, 2UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 0 || mat2(0,0,2) != 6 || + mat2(0,1,0) != 2 || mat2(0,1,1) != 0 || mat2(0,1,2) != 4 || + mat2(1,0,0) != 1 || mat2(1,0,1) != 0 || mat2(1,0,2) != 6 || + mat2(1,1,0) != 2 || mat2(1,1,1) != 0 || mat2(1,1,2) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 1 0 6 )\n( 2 0 4 ))\n(( 1 0 6 )\n( 2 0 4 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + +} // namespace customarray + +} // namespace mathtest + +} // namespace blazetest + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + std::cout << " Running aligned/padded CustomArray class test (part 1)..." << std::endl; + + try + { + RUN_CUSTOMARRAY_ALIGNED_PADDED_TEST; + } + catch( std::exception& ex ) { + std::cerr << "\n\n ERROR DETECTED during aligned/padded CustomArray class test (part 1):\n" + << ex.what() << "\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +//************************************************************************************************* diff --git a/blazetest/src/mathtest/customarray/AlignedPaddedTest2.cpp b/blazetest/src/mathtest/customarray/AlignedPaddedTest2.cpp new file mode 100644 index 0000000..9607504 --- /dev/null +++ b/blazetest/src/mathtest/customarray/AlignedPaddedTest2.cpp @@ -0,0 +1,2629 @@ +//================================================================================================= +/*! +// \file src/mathtest/customarray/AlignedPaddedTest2.cpp +// \brief Source file for the aligned/padded CustomArray class test (part 2) +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace blazetest { + +namespace mathtest { + +namespace customarray { + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constructor for the CustomArray class test. +// +// \exception std::runtime_error Operation error detected. +*/ +AlignedPaddedTest::AlignedPaddedTest() +{ + testSchurAssign(); + testMultAssign(); + testScaling(); + testFunctionCall(); + testAt(); + testIterator(); + testNonZeros(); + testReset(); + testClear(); + testSwap(); + testTranspose(); + testCTranspose(); + testIsDefault(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Test of the CustomArray Schur product assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the Schur product assignment operators of the CustomArray +// class template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testSchurAssign() +{ + //===================================================================================== + // Row-major dense tensor Schur product assignment + //===================================================================================== + + { + test_ = "Row-major/row-major CustomArray dense tensor Schur product assignment (mixed type)"; + + using blaze::aligned; + using blaze::padded; + + using AlignedPadded = blaze::CustomArray<3,short,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1 = 0; + mat1(0,0,0) = -1; + mat1(0,0,1) = -2; + mat1(0,1,0) = 3; + mat1(0,1,2) = -4; + mat1(1,0,0) = -1; + mat1(1,0,1) = -2; + mat1(1,1,0) = 3; + mat1(1,1,2) = -4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 %= mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 4UL ); + checkNonZeros( mat2, 0UL, 0UL, 1UL ); + checkNonZeros( mat2, 1UL, 0UL, 1UL ); + checkNonZeros( mat2, 0UL, 1UL, 1UL ); + checkNonZeros( mat2, 1UL, 1UL, 1UL ); + + if( mat2(0,0,0) != 0 || mat2(0,0,1) != 4 || mat2(0,0,2) != 0 || + mat2(0,1,0) != 15 || mat2(0,1,1) != 0 || mat2(0,1,2) != 0 || + mat2(1,0,0) != 0 || mat2(1,0,1) != 4 || mat2(1,0,2) != 0 || + mat2(1,1,0) != 15 || mat2(1,1,1) != 0 || mat2(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur product assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 0 4 0 )\n( 15 0 0 ))\n(( 0 4 0 )\n( 15 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor Schur product assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + using AlignedPadded = blaze::CustomArray<3,int,aligned,padded>; + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + AlignedPadded mat1( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat1 = 0; + mat1(0,0,0) = -1; + mat1(0,0,1) = -2; + mat1(0,1,0) = 3; + mat1(0,1,2) = -4; + mat1(1,0,0) = -1; + mat1(1,0,1) = -2; + mat1(1,1,0) = 3; + mat1(1,1,2) = -4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 %= mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 4UL ); + checkNonZeros( mat2, 0UL, 0UL, 1UL ); + checkNonZeros( mat2, 1UL, 0UL, 1UL ); + checkNonZeros( mat2, 0UL, 1UL, 1UL ); + checkNonZeros( mat2, 1UL, 1UL, 1UL ); + + if( mat2(0,0,0) != 0 || mat2(0,0,1) != 4 || mat2(0,0,2) != 0 || + mat2(0,1,0) != 15 || mat2(0,1,1) != 0 || mat2(0,1,2) != 0 || + mat2(1,0,0) != 0 || mat2(1,0,1) != 4 || mat2(1,0,2) != 0 || + mat2(1,1,0) != 15 || mat2(1,1,1) != 0 || mat2(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur product assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 0 4 0 )\n( 15 0 0 ))\n(( 0 4 0 )\n( 15 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major/row-major CustomArray dense tensor Schur product assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + using UnalignedUnpadded = blaze::CustomArray<3,int,unaligned,unpadded>; + std::unique_ptr memory1( new int[13UL] ); + UnalignedUnpadded mat1( memory1.get()+1UL, 2UL, 2UL, 3UL ); + mat1 = 0; + mat1(0,0,0) = -1; + mat1(0,0,1) = -2; + mat1(0,1,0) = 3; + mat1(0,1,2) = -4; + mat1(1,0,0) = -1; + mat1(1,0,1) = -2; + mat1(1,1,0) = 3; + mat1(1,1,2) = -4; + + std::unique_ptr memory2( blaze::allocate( 64UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 3UL, 16UL ); + mat2 = 0; + mat2(0,0,1) = -2; + mat2(0,0,2) = 6; + mat2(0,1,0) = 5; + mat2(1,0,1) = -2; + mat2(1,0,2) = 6; + mat2(1,1,0) = 5; + + mat2 %= mat1; + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 3UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + checkNonZeros( mat2, 4UL ); + checkNonZeros( mat2, 0UL, 0UL, 1UL ); + checkNonZeros( mat2, 1UL, 0UL, 1UL ); + checkNonZeros( mat2, 0UL, 1UL, 1UL ); + checkNonZeros( mat2, 1UL, 1UL, 1UL ); + + if( mat2(0,0,0) != 0 || mat2(0,0,1) != 4 || mat2(0,0,2) != 0 || + mat2(0,1,0) != 15 || mat2(0,1,1) != 0 || mat2(0,1,2) != 0 || + mat2(1,0,0) != 0 || mat2(1,0,1) != 4 || mat2(1,0,2) != 0 || + mat2(1,1,0) != 15 || mat2(1,1,1) != 0 || mat2(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur product assignment failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 0 4 0 )\n( 15 0 0 ))\n(( 0 4 0 )\n( 15 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the CustomArray multiplication assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the multiplication assignment operators of the CustomArray +// class template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testMultAssign() +{ +// //===================================================================================== +// // Row-major dense tensor multiplication assignment +// //===================================================================================== +// +// { +// test_ = "Row-major/row-major CustomArray dense tensor multiplication assignment (mixed type)"; +// +// using blaze::aligned; +// using blaze::padded; +// +// using AlignedPadded = blaze::CustomArray<3,short,aligned,padded>; +// std::unique_ptr memory1( blaze::allocate( 48UL ) ); +// AlignedPadded mat1( memory1.get(), 16UL, 3UL, 3UL ); +// mat1 = 0; +// mat1(0,1) = 2; +// mat1(1,0) = 1; +// mat1(1,1) = 3; +// mat1(1,2) = 4; +// mat1(2,2) = 5; +// +// std::unique_ptr memory2( blaze::allocate( 48UL ) ); +// MT mat2( memory2.get(), 16UL, 3UL, 3UL ); +// mat2 = 0; +// mat2(0,0) = 1; +// mat2(0,2) = 2; +// mat2(1,1) = 3; +// mat2(2,0) = 4; +// mat2(2,2) = 5; +// +// mat2 *= mat1; +// +// checkRows ( mat2, 3UL ); +// checkColumns ( mat2, 3UL ); +// checkNonZeros( mat2, 7UL ); +// checkNonZeros( mat2, 0UL, 2UL ); +// checkNonZeros( mat2, 1UL, 3UL ); +// checkNonZeros( mat2, 2UL, 2UL ); +// +// if( mat2(0,0) != 0 || mat2(0,1) != 2 || mat2(0,2) != 10 || +// mat2(1,0) != 3 || mat2(1,1) != 9 || mat2(1,2) != 12 || +// mat2(2,0) != 0 || mat2(2,1) != 8 || mat2(2,2) != 25 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << mat2 << "\n" +// << " Expected result:\n( 0 2 10 )\n( 3 9 12 )\n( 0 8 25 )\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "Row-major/row-major CustomArray dense tensor multiplication assignment (aligned/padded)"; +// +// using blaze::aligned; +// using blaze::padded; +// +// using AlignedPadded = blaze::CustomArray<3,int,aligned,padded>; +// std::unique_ptr memory1( blaze::allocate( 48UL ) ); +// AlignedPadded mat1( memory1.get(), 16UL, 3UL, 3UL ); +// mat1 = 0; +// mat1(0,1) = 2; +// mat1(1,0) = 1; +// mat1(1,1) = 3; +// mat1(1,2) = 4; +// mat1(2,2) = 5; +// +// std::unique_ptr memory2( blaze::allocate( 48UL ) ); +// MT mat2( memory2.get(), 16UL, 3UL, 3UL ); +// mat2 = 0; +// mat2(0,0) = 1; +// mat2(0,2) = 2; +// mat2(1,1) = 3; +// mat2(2,0) = 4; +// mat2(2,2) = 5; +// +// mat2 *= mat1; +// +// checkRows ( mat2, 3UL ); +// checkColumns ( mat2, 3UL ); +// checkNonZeros( mat2, 7UL ); +// checkNonZeros( mat2, 0UL, 2UL ); +// checkNonZeros( mat2, 1UL, 3UL ); +// checkNonZeros( mat2, 2UL, 2UL ); +// +// if( mat2(0,0) != 0 || mat2(0,1) != 2 || mat2(0,2) != 10 || +// mat2(1,0) != 3 || mat2(1,1) != 9 || mat2(1,2) != 12 || +// mat2(2,0) != 0 || mat2(2,1) != 8 || mat2(2,2) != 25 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << mat2 << "\n" +// << " Expected result:\n( 0 2 10 )\n( 3 9 12 )\n( 0 8 25 )\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "Row-major/row-major CustomArray dense tensor multiplication assignment (unaligned/unpadded)"; +// +// using blaze::unaligned; +// using blaze::unpadded; +// +// using UnalignedUnpadded = blaze::CustomArray<3,int,unaligned,unpadded>; +// std::unique_ptr memory1( new int[10UL] ); +// UnalignedUnpadded mat1( memory1.get()+1UL, 3UL, 3UL ); +// mat1 = 0; +// mat1(0,1) = 2; +// mat1(1,0) = 1; +// mat1(1,1) = 3; +// mat1(1,2) = 4; +// mat1(2,2) = 5; +// +// std::unique_ptr memory2( blaze::allocate( 48UL ) ); +// MT mat2( memory2.get(), 3UL, 3UL, 16UL ); +// mat2 = 0; +// mat2(0,0) = 1; +// mat2(0,2) = 2; +// mat2(1,1) = 3; +// mat2(2,0) = 4; +// mat2(2,2) = 5; +// +// mat2 *= mat1; +// +// checkRows ( mat2, 3UL ); +// checkColumns ( mat2, 3UL ); +// checkNonZeros( mat2, 7UL ); +// checkNonZeros( mat2, 0UL, 2UL ); +// checkNonZeros( mat2, 1UL, 3UL ); +// checkNonZeros( mat2, 2UL, 2UL ); +// +// if( mat2(0,0) != 0 || mat2(0,1) != 2 || mat2(0,2) != 10 || +// mat2(1,0) != 3 || mat2(1,1) != 9 || mat2(1,2) != 12 || +// mat2(2,0) != 0 || mat2(2,1) != 8 || mat2(2,2) != 25 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << mat2 << "\n" +// << " Expected result:\n( 0 2 10 )\n( 3 9 12 )\n( 0 8 25 )\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of all CustomArray (self-)scaling operations. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all available ways to scale an instance of the CustomArray +// class template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testScaling() +{ + //===================================================================================== + // Row-major self-scaling (M*=s) + //===================================================================================== + + { + test_ = "Row-major self-scaling (M*=s)"; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 3UL, 16UL ); + mat = 0; + mat(0,1,2) = 1; + mat(0,2,0) = -2; + mat(0,2,2) = 3; + mat(1,1,2) = 1; + mat(1,2,0) = -2; + mat(1,2,2) = 3; + + mat *= 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 2 || + mat(0,2,0) != -4 || mat(0,2,1) != 0 || mat(0,2,2) != 6 || + mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 2 || + mat(0,2,0) != -4 || mat(0,2,1) != 0 || mat(0,2,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 2 )\n( -4 0 6 ))\n(( 0 0 0 )\n( 0 0 2 )\n( -4 0 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major self-scaling (M=M*s) + //===================================================================================== + + { + test_ = "Row-major self-scaling (M=M*s)"; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 3UL, 16UL ); + mat = 0; + mat(0,1,2) = 1; + mat(0,2,0) = -2; + mat(0,2,2) = 3; + mat(1,1,2) = 1; + mat(1,2,0) = -2; + mat(1,2,2) = 3; + + mat = mat * 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 2 || + mat(0,2,0) != -4 || mat(0,2,1) != 0 || mat(0,2,2) != 6 || + mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 2 || + mat(0,2,0) != -4 || mat(0,2,1) != 0 || mat(0,2,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 2 )\n( -4 0 6 ))\n(( 0 0 0 )\n( 0 0 2 )\n( -4 0 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major self-scaling (M=s*M) + //===================================================================================== + + { + test_ = "Row-major self-scaling (M=s*M)"; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 3UL, 16UL ); + mat = 0; + mat(0,1,2) = 1; + mat(0,2,0) = -2; + mat(0,2,2) = 3; + mat(1,1,2) = 1; + mat(1,2,0) = -2; + mat(1,2,2) = 3; + + mat = 2 * mat; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 2 || + mat(0,2,0) != -4 || mat(0,2,1) != 0 || mat(0,2,2) != 6 || + mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 2 || + mat(0,2,0) != -4 || mat(0,2,1) != 0 || mat(0,2,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 2 )\n( -4 0 6 ))\n(( 0 0 0 )\n( 0 0 2 )\n( -4 0 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major self-scaling (M/=s) + //===================================================================================== + + { + test_ = "Row-major self-scaling (M/=s)"; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 3UL, 16UL ); + mat = 0; + mat(0,1,2) = 2; + mat(0,2,0) = -4; + mat(0,2,2) = 6; + mat(1,1,2) = 2; + mat(1,2,0) = -4; + mat(1,2,2) = 6; + + mat /= 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 1 || + mat(0,2,0) != -2 || mat(0,2,1) != 0 || mat(0,2,2) != 3 || + mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 1 || + mat(0,2,0) != -2 || mat(0,2,1) != 0 || mat(0,2,2) != 3 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 1 )\n( -2 0 3 ))\n(( 0 0 0 )\n( 0 0 1 )\n( -2 0 3 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major self-scaling (M=M/s) + //===================================================================================== + + { + test_ = "Row-major self-scaling (M=M/s)"; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 3UL, 16UL ); + mat = 0; + mat(0,1,2) = 2; + mat(0,2,0) = -4; + mat(0,2,2) = 6; + mat(1,1,2) = 2; + mat(1,2,0) = -4; + mat(1,2,2) = 6; + + mat = mat / 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 1 || + mat(0,2,0) != -2 || mat(0,2,1) != 0 || mat(0,2,2) != 3 || + mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 1 || + mat(0,2,0) != -2 || mat(0,2,1) != 0 || mat(0,2,2) != 3 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 1 )\n( -2 0 3 ))\n(( 0 0 0 )\n( 0 0 1 )\n( -2 0 3 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major CustomArray::scale() + //===================================================================================== + + { + test_ = "Row-major CustomArray::scale() (int)"; + + // Initialization check + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 2UL, 16UL ); + mat(0,0,0) = 1; + mat(0,0,1) = 2; + mat(0,1,0) = 3; + mat(0,1,1) = 4; + mat(0,2,0) = 5; + mat(0,2,1) = 6; + mat(1,0,0) = 1; + mat(1,0,1) = 2; + mat(1,1,0) = 3; + mat(1,1,1) = 4; + mat(1,2,0) = 5; + mat(1,2,1) = 6; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 2UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 2UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || + mat(0,1,0) != 3 || mat(0,1,1) != 4 || + mat(0,2,0) != 5 || mat(0,2,1) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || + mat(1,1,0) != 3 || mat(1,1,1) != 4 || + mat(1,2,0) != 5 || mat(1,2,1) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 )\n( 3 4 )\n( 5 6 ))\n(( 1 2 )\n( 3 4 )\n( 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Integral scaling of the tensor + mat.scale( 2 ); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 2UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 2UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 2 || mat(0,0,1) != 4 || + mat(0,1,0) != 6 || mat(0,1,1) != 8 || + mat(0,2,0) != 10 || mat(0,2,1) != 12 || + mat(1,0,0) != 2 || mat(1,0,1) != 4 || + mat(1,1,0) != 6 || mat(1,1,1) != 8 || + mat(1,2,0) != 10 || mat(1,2,1) != 12 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Scale operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 2 4 )\n( 6 8 )\n( 10 12 ))\n(( 2 4 )\n( 6 8 )\n( 10 12 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Floating point scaling of the tensor + mat.scale( 0.5 ); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 2UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 2UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || + mat(0,1,0) != 3 || mat(0,1,1) != 4 || + mat(0,2,0) != 5 || mat(0,2,1) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || + mat(1,1,0) != 3 || mat(1,1,1) != 4 || + mat(1,2,0) != 5 || mat(1,2,1) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Scale operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 )\n( 3 4 )\n( 5 6 ))\n(( 1 2 )\n( 3 4 )\n( 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "Row-major CustomArray::scale() (complex)"; + + using blaze::complex; + using blaze::aligned; + using blaze::padded; + using blaze::rowMajor; + + using cplx = complex; + using AlignedPadded = blaze::CustomArray<3,cplx,aligned,padded>; + std::unique_ptr memory( blaze::allocate( 64UL ) ); + AlignedPadded mat( memory.get(), 2UL, 2UL, 2UL, 16UL ); + mat(0,0,0) = cplx( 1.0F, 0.0F ); + mat(0,0,1) = cplx( 2.0F, 0.0F ); + mat(0,1,0) = cplx( 3.0F, 0.0F ); + mat(0,1,1) = cplx( 4.0F, 0.0F ); + mat(1,0,0) = cplx( 1.0F, 0.0F ); + mat(1,0,1) = cplx( 2.0F, 0.0F ); + mat(1,1,0) = cplx( 3.0F, 0.0F ); + mat(1,1,1) = cplx( 4.0F, 0.0F ); + mat.scale( cplx( 3.0F, 0.0F ) ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 2UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 32UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 2UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + + if( mat(0,0,0) != cplx( 3.0F, 0.0F ) || mat(0,0,1) != cplx( 6.0F, 0.0F ) || + mat(0,1,0) != cplx( 9.0F, 0.0F ) || mat(0,1,1) != cplx( 12.0F, 0.0F ) || + mat(1,0,0) != cplx( 3.0F, 0.0F ) || mat(1,0,1) != cplx( 6.0F, 0.0F ) || + mat(1,1,0) != cplx( 9.0F, 0.0F ) || mat(1,1,1) != cplx( 12.0F, 0.0F ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Scale operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( ( 3,0) ( 6,0)\n( 9,0) (12,0) ))\n(( ( 3,0) ( 6,0)\n( 9,0) (12,0) ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the CustomArray function call operator. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of adding and accessing elements via the function call operator +// of the CustomArray class template. In case an error is detected, a \a std::runtime_error +// exception is thrown. +*/ +void AlignedPaddedTest::testFunctionCall() +{ + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + test_ = "Row-major CustomArray::operator()"; + + // Assignment to the element (2,1,x) + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 5UL, 16UL ); + mat = 0; + mat(0,2,1) = 1; + mat(1,2,1) = 1; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 2UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 0UL ); + checkNonZeros( mat, 2UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 0UL ); + checkNonZeros( mat, 2UL, 1UL, 1UL ); + + if( mat(0,2,1) != 1 || mat(1,2,1) != 1) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 0 0 )\n( 0 0 0 0 0 )\n( 0 1 0 0 0 ))\n(( 0 0 0 0 0 )\n( 0 0 0 0 0 )\n( 0 1 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element (1,4) + mat(0,1,4) = 2; + mat(1,1,4) = 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 4UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 1UL ); + + if( mat(0,1,4) != 2 || mat(0,2,1) != 1 || + mat(1,1,4) != 2 || mat(1,2,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 0 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n(( 0 0 0 0 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element (0,3) + mat(0,0,3) = 3; + mat(1,0,3) = 3; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 1UL ); + + if( mat(0,0,3) != 3 || mat(0,1,4) != 2 || mat(0,2,1) != 1 || + mat(1,0,3) != 3 || mat(1,1,4) != 2 || mat(1,2,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element (2,2) + mat(0,2,2) = 4; + mat(1,2,2) = 4; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,3) != 3 || mat(0,1,4) != 2 || mat(0,2,2) != 4 || mat(0,2,1) != 1 || + mat(1,0,3) != 3 || mat(1,1,4) != 2 || mat(1,2,2) != 4 || mat(1,2,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 4 0 0 ))\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Addition assignment to the element (2,1) + mat(0,2,1) += mat(0,0,3); + mat(1,2,1) += mat(1,0,3); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,3) != 3 || mat(0,1,4) != 2 || mat(0,2,2) != 4 || mat(0,2,1) != 4 || + mat(1,0,3) != 3 || mat(1,1,4) != 2 || mat(1,2,2) != 4 || mat(1,2,1) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 4 4 0 0 ))\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 4 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Subtraction assignment to the element (1,0) + mat(0,1,0) -= mat(0,1,4); + mat(1,1,0) -= mat(1,1,4); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 10UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,3) != 3 || mat(0,1,0) != -2 || mat(0,1,4) != 2 || mat(0,2,2) != 4 || mat(0,2,1) != 4 || + mat(1,0,3) != 3 || mat(1,1,0) != -2 || mat(1,1,4) != 2 || mat(1,2,2) != 4 || mat(1,2,1) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n(( 0 0 0 3 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Multiplication assignment to the element (0,3) + mat(0,0,3) *= -3; + mat(1,0,3) *= -3; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 10UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,3) != -9 || mat(0,1,0) != -2 || mat(0,1,4) != 2 || mat(0,2,2) != 4 || mat(0,2,1) != 4 || + mat(1,0,3) != -9 || mat(1,1,0) != -2 || mat(1,1,4) != 2 || mat(1,2,2) != 4 || mat(1,2,1) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Division assignment to the element (2,1) + mat(0,2,1) /= 2; + mat(1,2,1) /= 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 10UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat(0,0,3) != -9 || mat(0,1,0) != -2 || mat(0,1,4) != 2 || mat(0,2,2) != 4 || mat(0,2,1) != 2 || + mat(1,0,3) != -9 || mat(1,1,0) != -2 || mat(1,1,4) != 2 || mat(1,2,2) != 4 || mat(1,2,1) != 2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c at() member function of the CustomArray function call operator. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of adding and accessing elements via the \c at() member function +// of the CustomArray class template. In case an error is detected, a \a std::runtime_error +// exception is thrown. +*/ +void AlignedPaddedTest::testAt() +{ + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + test_ = "Row-major CustomArray::at()"; + + // Assignment to the element (2,1,x) + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 5UL, 16UL ); + mat = 0; + mat.at(0,2,1) = 1; + mat.at(1,2,1) = 1; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 2UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 0UL ); + checkNonZeros( mat, 2UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 0UL ); + checkNonZeros( mat, 2UL, 1UL, 1UL ); + + if( mat.at(0,2,1) != 1 || mat.at(1,2,1) != 1) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 0 0 )\n( 0 0 0 0 0 )\n( 0 1 0 0 0 ))\n(( 0 0 0 0 0 )\n( 0 0 0 0 0 )\n( 0 1 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element (1,4) + mat.at(0,1,4) = 2; + mat.at(1,1,4) = 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 4UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 1UL ); + + if( mat.at(0,1,4) != 2 || mat.at(0,2,1) != 1 || + mat.at(1,1,4) != 2 || mat.at(1,2,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 0 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n(( 0 0 0 0 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element (0,3) + mat.at(0,0,3) = 3; + mat.at(1,0,3) = 3; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 1UL ); + + if( mat.at(0,0,3) != 3 || mat.at(0,1,4) != 2 || mat.at(0,2,1) != 1 || + mat.at(1,0,3) != 3 || mat.at(1,1,4) != 2 || mat.at(1,2,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element (2,2) + mat.at(0,2,2) = 4; + mat.at(1,2,2) = 4; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat.at(0,0,3) != 3 || mat.at(0,1,4) != 2 || mat.at(0,2,2) != 4 || mat.at(0,2,1) != 1 || + mat.at(1,0,3) != 3 || mat.at(1,1,4) != 2 || mat.at(1,2,2) != 4 || mat.at(1,2,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 4 0 0 ))\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 1 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Addition assignment to the element (2,1) + mat.at(0,2,1) += mat.at(0,0,3); + mat.at(1,2,1) += mat.at(1,0,3); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat.at(0,0,3) != 3 || mat.at(0,1,4) != 2 || mat.at(0,2,2) != 4 || mat.at(0,2,1) != 4 || + mat.at(1,0,3) != 3 || mat.at(1,1,4) != 2 || mat.at(1,2,2) != 4 || mat.at(1,2,1) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 4 4 0 0 ))\n(( 0 0 0 3 0 )\n( 0 0 0 0 2 )\n( 0 4 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Subtraction assignment to the element (1,0) + mat.at(0,1,0) -= mat.at(0,1,4); + mat.at(1,1,0) -= mat.at(1,1,4); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 10UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat.at(0,0,3) != 3 || mat.at(0,1,0) != -2 || mat.at(0,1,4) != 2 || mat.at(0,2,2) != 4 || mat.at(0,2,1) != 4 || + mat.at(1,0,3) != 3 || mat.at(1,1,0) != -2 || mat.at(1,1,4) != 2 || mat.at(1,2,2) != 4 || mat.at(1,2,1) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 3 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n(( 0 0 0 3 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Multiplication assignment to the element (0,3) + mat.at(0,0,3) *= -3; + mat.at(1,0,3) *= -3; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 10UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat.at(0,0,3) != -9 || mat.at(0,1,0) != -2 || mat.at(0,1,4) != 2 || mat.at(0,2,2) != 4 || mat.at(0,2,1) != 4 || + mat.at(1,0,3) != -9 || mat.at(1,1,0) != -2 || mat.at(1,1,4) != 2 || mat.at(1,2,2) != 4 || mat.at(1,2,1) != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 4 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Division assignment to the element (2,1) + mat.at(0,2,1) /= 2; + mat.at(1,2,1) /= 2; + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + checkNonZeros( mat, 10UL ); + checkNonZeros( mat, 0UL, 0UL, 1UL ); + checkNonZeros( mat, 1UL, 0UL, 2UL ); + checkNonZeros( mat, 2UL, 0UL, 2UL ); + checkNonZeros( mat, 0UL, 1UL, 1UL ); + checkNonZeros( mat, 1UL, 1UL, 2UL ); + checkNonZeros( mat, 2UL, 1UL, 2UL ); + + if( mat.at(0,0,3) != -9 || mat.at(0,1,0) != -2 || mat.at(0,1,4) != 2 || mat.at(0,2,2) != 4 || mat.at(0,2,1) != 2 || + mat.at(1,0,3) != -9 || mat.at(1,1,0) != -2 || mat.at(1,1,4) != 2 || mat.at(1,2,2) != 4 || mat.at(1,2,1) != 2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Attempt to assign to the element (0,3,0) + try { + mat.at(0,3,0) = 2; + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Out-of-bound access succeeded\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::out_of_range& ) {} + + // Attempt to assign to the element (1,0,5) + try { + mat.at(1,0,5) = 2; + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Out-of-bound access succeeded\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::out_of_range& ) {} + + // Attempt to assign to the element (3,0,1) + try { + mat.at(3,0,1) = 2; + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Out-of-bound access succeeded\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n(( 0 0 0 -9 0 )\n( -2 0 0 0 2 )\n( 0 2 4 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::out_of_range& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the CustomArray iterator implementation. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the iterator implementation of the CustomArray class +// template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testIterator() +{ + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + using Iterator = MT::Iterator; + using ConstIterator = MT::ConstIterator; + + std::unique_ptr memory( blaze::allocate( 96UL ) ); + MT mat( memory.get(), 2UL, 3UL, 3UL, 16UL ); + mat = 0; + mat(0,0,1) = 1; + mat(0,1,0) = -2; + mat(0,1,2) = -3; + mat(0,2,1) = 4; + mat(0,2,2) = 5; + mat(1,0,1) = 1; + mat(1,1,0) = -2; + mat(1,1,2) = -3; + mat(1,2,1) = 4; + mat(1,2,2) = 5; + + // Testing the Iterator default constructor + { + test_ = "Row-major Iterator default constructor"; + + Iterator it{}; + + if( it != Iterator() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator default constructor\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing the ConstIterator default constructor + { + test_ = "Row-major ConstIterator default constructor"; + + ConstIterator it{}; + + if( it != ConstIterator() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator default constructor\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing conversion from Iterator to ConstIterator + { + test_ = "Row-major Iterator/ConstIterator conversion"; + + ConstIterator it( begin( mat, 1UL, 0UL ) ); + + if( it == end( mat, 1UL, 0UL ) || *it != -2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator conversion detected\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 0th row via Iterator (end-begin) + { + test_ = "Row-major Iterator subtraction (end-begin)"; + + const ptrdiff_t number( end( mat, 0UL, 1UL ) - begin( mat, 0UL, 1UL ) ); + + if( number != 3L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: 3\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 0th row via Iterator (begin-end) + { + test_ = "Row-major Iterator subtraction (begin-end)"; + + const ptrdiff_t number( begin( mat, 0UL, 0UL ) - end( mat, 0UL, 0UL ) ); + + if( number != -3L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: -3\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 1st row via ConstIterator (end-begin) + { + test_ = "Row-major ConstIterator subtraction (end-begin)"; + + const ptrdiff_t number( cend( mat, 1UL, 1UL ) - cbegin( mat, 1UL, 1UL ) ); + + if( number != 3L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: 3\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 1st row via ConstIterator (begin-end) + { + test_ = "Row-major ConstIterator subtraction (begin-end)"; + + const ptrdiff_t number( cbegin( mat, 1UL, 0UL ) - cend( mat, 1UL, 0UL ) ); + + if( number != -3L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: -3\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing read-only access via ConstIterator + { + test_ = "Row-major read-only access via ConstIterator"; + + ConstIterator it ( cbegin( mat, 2UL, 0UL ) ); + ConstIterator end( cend( mat, 2UL, 0UL ) ); + + if( it == end || *it != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid initial iterator detected\n"; + throw std::runtime_error( oss.str() ); + } + + ++it; + + if( it == end || *it != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator pre-increment failed\n"; + throw std::runtime_error( oss.str() ); + } + + --it; + + if( it == end || *it != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator pre-decrement failed\n"; + throw std::runtime_error( oss.str() ); + } + + it++; + + if( it == end || *it != 4 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator post-increment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it--; + + if( it == end || *it != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator post-decrement failed\n"; + throw std::runtime_error( oss.str() ); + } + + it += 2UL; + + if( it == end || *it != 5 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator addition assignment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it -= 2UL; + + if( it == end || *it != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator subtraction assignment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = it + 2UL; + + if( it == end || *it != 5 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator/scalar addition failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = it - 2UL; + + if( it == end || *it != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator/scalar subtraction failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = 3UL + it; + + if( it != end ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Scalar/iterator addition failed\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing assignment via Iterator + { + test_ = "Row-major assignment via Iterator"; + + int value = 7; + + for( Iterator it=begin( mat, 2UL, 1UL ); it!=end( mat, 2UL, 1UL ); ++it ) { + *it = value++; + } + + if( mat(0,0,0) != 0 || mat(0,0,1) != 1 || mat(0,0,2) != 0 || + mat(0,1,0) != -2 || mat(0,1,1) != 0 || mat(0,1,2) != -3 || + mat(0,2,0) != 0 || mat(0,2,1) != 4 || mat(0,2,2) != 5 || + mat(1,0,0) != 0 || mat(1,0,1) != 1 || mat(1,0,2) != 0 || + mat(1,1,0) != -2 || mat(1,1,1) != 0 || mat(1,1,2) != -3 || + mat(1,2,0) != 7 || mat(1,2,1) != 8 || mat(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 1 0 )\n( -2 0 -3 )\n( 0 4 5 ))\n(( 0 1 0 )\n( -2 0 -3 )\n( 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing addition assignment via Iterator + { + test_ = "Row-major addition assignment via Iterator"; + + int value = 4; + + for( Iterator it=begin( mat, 1UL, 0UL ); it!=end( mat, 1UL, 0UL ); ++it ) { + *it += value++; + } + + if( mat(0,0,0) != 0 || mat(0,0,1) != 1 || mat(0,0,2) != 0 || + mat(0,1,0) != 2 || mat(0,1,1) != 5 || mat(0,1,2) != 3 || + mat(0,2,0) != 0 || mat(0,2,1) != 4 || mat(0,2,2) != 5 || + mat(1,0,0) != 0 || mat(1,0,1) != 1 || mat(1,0,2) != 0 || + mat(1,1,0) != -2 || mat(1,1,1) != 0 || mat(1,1,2) != -3 || + mat(1,2,0) != 7 || mat(1,2,1) != 8 || mat(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 1 0 )\n( 2 5 3 )\n( 0 4 5 ))\n(( 0 1 0 )\n( -2 0 -3 )\n( 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing subtraction assignment via Iterator + { + test_ = "Row-major subtraction assignment via Iterator"; + + int value = 4; + + for( Iterator it=begin( mat, 1UL, 0UL ); it!=end( mat, 1UL, 0UL ); ++it ) { + *it -= value++; + } + + if( mat(0,0,0) != 0 || mat(0,0,1) != 1 || mat(0,0,2) != 0 || + mat(0,1,0) != -2 || mat(0,1,1) != 0 || mat(0,1,2) != -3 || + mat(0,2,0) != 0 || mat(0,2,1) != 4 || mat(0,2,2) != 5 || + mat(1,0,0) != 0 || mat(1,0,1) != 1 || mat(1,0,2) != 0 || + mat(1,1,0) != -2 || mat(1,1,1) != 0 || mat(1,1,2) != -3 || + mat(1,2,0) != 7 || mat(1,2,1) != 8 || mat(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 1 0 )\n( -2 0 -3 )\n( 0 4 5 ))\n(( 0 1 0 )\n( -2 0 -3 )\n( 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing multiplication assignment via Iterator + { + test_ = "Row-major multiplication assignment via Iterator"; + + int value = 2; + + for( Iterator it=begin( mat, 1UL, 0UL ); it!=end( mat, 1UL, 0UL ); ++it ) { + *it *= value++; + } + + if( mat(0,0,0) != 0 || mat(0,0,1) != 1 || mat(0,0,2) != 0 || + mat(0,1,0) != -4 || mat(0,1,1) != 0 || mat(0,1,2) != -12 || + mat(0,2,0) != 0 || mat(0,2,1) != 4 || mat(0,2,2) != 5 || + mat(1,0,0) != 0 || mat(1,0,1) != 1 || mat(1,0,2) != 0 || + mat(1,1,0) != -2 || mat(1,1,1) != 0 || mat(1,1,2) != -3 || + mat(1,2,0) != 7 || mat(1,2,1) != 8 || mat(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 1 0 )\n( -4 0 -12 )\n( 0 4 5 ))\n(( 0 1 0 )\n( -2 0 -3 )\n( 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing division assignment via Iterator + { + test_ = "Row-major division assignment via Iterator"; + + for( Iterator it=begin( mat, 1UL, 1UL ); it!=end( mat, 1UL, 1UL ); ++it ) { + *it /= 2; + } + + if( mat(0,0,0) != 0 || mat(0,0,1) != 1 || mat(0,0,2) != 0 || + mat(0,1,0) != -4 || mat(0,1,1) != 0 || mat(0,1,2) != -12 || + mat(0,2,0) != 0 || mat(0,2,1) != 4 || mat(0,2,2) != 5 || + mat(1,0,0) != 0 || mat(1,0,1) != 1 || mat(1,0,2) != 0 || + mat(1,1,0) != -1 || mat(1,1,1) != 0 || mat(1,1,2) != -1 || + mat(1,2,0) != 7 || mat(1,2,1) != 8 || mat(1,2,2) != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Division assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 1 0 )\n( -4 0 -12 )\n( 0 4 5 ))\n(( 0 1 0 )\n( -1 0 -1 )\n( 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c nonZeros() member function of the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c nonZeros() member function of the CustomArray class +// template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testNonZeros() +{ + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + test_ = "Row-major CustomArray::nonZeros()"; + + { + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat = 0; + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 0UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 0UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 0UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 0 || + mat(1,0,0) != 0 || mat(1,0,1) != 0 || mat(1,0,2) != 0 || + mat(1,1,0) != 0 || mat(1,1,1) != 0 || mat(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 0 ))\n(( 0 0 0 )\n( 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat = 0; + mat(0,0,1) = 1; + mat(0,0,2) = 2; + mat(0,1,1) = 3; + mat(1,0,1) = 1; + mat(1,0,2) = 2; + mat(1,1,1) = 3; + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 6UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 1UL ); + checkNonZeros( mat, 0UL, 1UL, 2UL ); + checkNonZeros( mat, 1UL, 1UL, 1UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 1 || mat(0,0,2) != 2 || + mat(0,1,0) != 0 || mat(0,1,1) != 3 || mat(0,1,2) != 0 || + mat(1,0,0) != 0 || mat(1,0,1) != 1 || mat(1,0,2) != 2 || + mat(1,1,0) != 0 || mat(1,1,1) != 3 || mat(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 1 2 )\n( 0 3 0 ))\n(( 0 1 2 )\n( 0 3 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c reset() member function of the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c reset() member function of the CustomArray class +// template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testReset() +{ + using blaze::reset; + + + //===================================================================================== + // Row-major CustomArray::reset() + //===================================================================================== + + { + test_ = "Row-major CustomArray::reset()"; + + // Initialization check + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat(0,0,0) = 1; + mat(0,0,1) = 2; + mat(0,0,2) = 3; + mat(0,1,0) = 4; + mat(0,1,1) = 5; + mat(0,1,2) = 6; + mat(1,0,0) = 1; + mat(1,0,1) = 2; + mat(1,0,2) = 3; + mat(1,1,0) = 4; + mat(1,1,1) = 5; + mat(1,1,2) = 6; + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 3UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 3 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Resetting a single element + reset( mat(0,0,2) ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 11UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 0 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 0 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Resetting row 1 + reset( mat, 1UL, 1UL ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 8UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 0UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 0 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 0 || mat(1,1,1) != 0 || mat(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 0 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Resetting the entire tensor + reset( mat ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 0UL ); + checkNonZeros( mat, 0UL, 0UL, 0UL ); + checkNonZeros( mat, 1UL, 0UL, 0UL ); + checkNonZeros( mat, 0UL, 1UL, 0UL ); + checkNonZeros( mat, 1UL, 1UL, 0UL ); + + if( mat(0,0,0) != 0 || mat(0,0,1) != 0 || mat(0,0,2) != 0 || + mat(0,1,0) != 0 || mat(0,1,1) != 0 || mat(0,1,2) != 0 || + mat(1,0,0) != 0 || mat(1,0,1) != 0 || mat(1,0,2) != 0 || + mat(1,1,0) != 0 || mat(1,1,1) != 0 || mat(1,1,2) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 0 0 0 )\n( 0 0 0 ))\n(( 0 0 0 )\n( 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // Row-major CustomArray::reset( Type*, size_t, size_t, size_t ) + //===================================================================================== + + { + test_ = "Row-major CustomArray::reset( Type*, size_t, size_t, size_t, size_t )"; + + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + MT mat( memory1.get(), 2UL, 2UL, 3UL, 16UL ); + mat = 2; + + std::unique_ptr memory2( blaze::allocate( 96UL ) ); + mat.reset( memory2.get(), 2UL, 3UL, 5UL, 16UL ); + + checkRows ( mat, 3UL ); + checkColumns ( mat, 5UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 96UL ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c clear() member function of the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c clear() member function of the CustomArray class +// template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testClear() +{ + using blaze::clear; + + + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + test_ = "Row-major CustomArray::clear()"; + + // Initialization check + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + mat(0,0,0) = 1; + mat(0,0,1) = 2; + mat(0,0,2) = 3; + mat(0,1,0) = 4; + mat(0,1,1) = 5; + mat(0,1,2) = 6; + mat(1,0,0) = 1; + mat(1,0,1) = 2; + mat(1,0,2) = 3; + mat(1,1,0) = 4; + mat(1,1,1) = 5; + mat(1,1,2) = 6; + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 12UL ); + checkNonZeros( mat, 0UL, 0UL, 3UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 3 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 3 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Clearing a single element + clear( mat(0,0,2) ); + + checkRows ( mat, 2UL ); + checkColumns ( mat, 3UL ); + checkPages ( mat, 2UL ); + checkCapacity( mat, 64UL ); + checkNonZeros( mat, 11UL ); + checkNonZeros( mat, 0UL, 0UL, 2UL ); + checkNonZeros( mat, 1UL, 0UL, 3UL ); + checkNonZeros( mat, 0UL, 1UL, 3UL ); + checkNonZeros( mat, 1UL, 1UL, 3UL ); + + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 0 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || + mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Clear operation failed\n" + << " Details:\n" + << " Result:\n" << mat << "\n" + << " Expected result:\n(( 1 2 0 )\n( 4 5 6 ))\n(( 1 2 3 )\n( 4 5 6 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Clearing the tensor + clear( mat ); + + checkRows ( mat, 0UL ); + checkColumns ( mat, 0UL ); + checkPages ( mat, 0UL ); + checkNonZeros( mat, 0UL ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c swap() functionality of the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c swap() function of the CustomArray class template. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testSwap() +{ + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + test_ = "Row-major CustomArray swap"; + + std::unique_ptr memory1( blaze::allocate( 64UL ) ); + MT mat1( memory1.get(), 2UL, 2UL, 2UL, 16UL ); + mat1(0,0,0) = 1; + mat1(0,0,1) = 2; + mat1(0,1,0) = 0; + mat1(0,1,1) = 3; + + std::unique_ptr memory2( blaze::allocate( 128UL ) ); + MT mat2( memory2.get(), 2UL, 2UL, 2UL, 32UL ); + mat2(1,0,0) = 4; + mat2(1,0,1) = 3; + mat2(1,1,0) = 2; + mat2(1,1,1) = 1; + + swap( mat1, mat2 ); + + checkRows ( mat1, 2UL ); + checkColumns ( mat1, 2UL ); + checkPages ( mat1, 2UL ); + checkCapacity( mat1, 128UL ); + + if( mat1(1,0,0) != 4 || mat1(1,0,1) != 3 || mat1(1,1,0) != 2 || mat1(1,1,1) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Swapping the first tensor failed\n" + << " Details:\n" + << " Result:\n" << mat1 << "\n" + << " Expected result:\n(( 4 3 )\n( 2 1 ))\n(( 0 0 )\n( 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + + checkRows ( mat2, 2UL ); + checkColumns ( mat2, 2UL ); + checkPages ( mat2, 2UL ); + checkCapacity( mat2, 64UL ); + + if( mat2(0,0,0) != 1 || mat2(0,0,1) != 2 || mat2(0,1,0) != 0 || mat2(0,1,1) != 3 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Swapping the second tensor failed\n" + << " Details:\n" + << " Result:\n" << mat2 << "\n" + << " Expected result:\n(( 0 0 )\n( 0 0 ))\n(( 1 2 )\n( 0 3 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c transpose() member function of the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c transpose() member function of the CustomArray +// class template. Additionally, it performs a test of self-transpose via the \c trans() +// function. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testTranspose() +{ +// //===================================================================================== +// // Row-major tensor tests +// //===================================================================================== +// +// { +// test_ = "Row-major self-transpose via transpose()"; +// +// // Self-transpose of a 3x3x3 tensor +// { +// std::unique_ptr memory( blaze::allocate( 432UL ) ); +// MT mat( memory.get(), 3UL, 3UL, 3UL, 16UL ); +// mat(0,0,0) = 1; +// mat(0,0,1) = 2; +// mat(0,0,2) = 3; +// mat(0,1,0) = 4; +// mat(0,1,1) = 5; +// mat(0,1,2) = 6; +// mat(0,2,0) = 7; +// mat(0,2,1) = 8; +// mat(0,2,2) = 9; +// mat(1,0,0) = 1; +// mat(1,0,1) = 2; +// mat(1,0,2) = 3; +// mat(1,1,0) = 4; +// mat(1,1,1) = 5; +// mat(1,1,2) = 6; +// mat(1,2,0) = 7; +// mat(1,2,1) = 8; +// mat(1,2,2) = 9; +// mat(2,0,0) = 1; +// mat(2,0,1) = 2; +// mat(2,0,2) = 3; +// mat(2,1,0) = 4; +// mat(2,1,1) = 5; +// mat(2,1,2) = 6; +// mat(2,2,0) = 7; +// mat(2,2,1) = 8; +// mat(2,2,2) = 9; +// +// transpose(mat, {2, 1, 0}); +// +// checkRows ( mat, 3UL ); +// checkColumns ( mat, 3UL ); +// checkPages ( mat, 3UL ); +// checkCapacity( mat, 27UL ); +// checkNonZeros( mat, 27UL ); +// checkNonZeros( mat, 0UL, 0UL, 3UL ); +// checkNonZeros( mat, 1UL, 0UL, 3UL ); +// checkNonZeros( mat, 2UL, 0UL, 3UL ); +// checkNonZeros( mat, 0UL, 1UL, 3UL ); +// checkNonZeros( mat, 1UL, 1UL, 3UL ); +// checkNonZeros( mat, 2UL, 1UL, 3UL ); +// checkNonZeros( mat, 0UL, 2UL, 3UL ); +// checkNonZeros( mat, 1UL, 2UL, 3UL ); +// checkNonZeros( mat, 2UL, 2UL, 3UL ); +// +// if( mat(0,0,0) != 1 || mat(1,0,0) != 2 || mat(2,0,0) != 3 || +// mat(0,1,0) != 4 || mat(1,1,0) != 5 || mat(2,1,0) != 6 || +// mat(0,2,0) != 7 || mat(1,2,0) != 8 || mat(2,2,0) != 9 || +// mat(0,0,1) != 1 || mat(1,0,1) != 2 || mat(2,0,1) != 3 || +// mat(0,1,1) != 4 || mat(1,1,1) != 5 || mat(2,1,1) != 6 || +// mat(0,2,1) != 7 || mat(1,2,1) != 8 || mat(2,2,1) != 9 || +// mat(0,0,2) != 1 || mat(1,0,2) != 2 || mat(2,0,2) != 3 || +// mat(0,1,2) != 4 || mat(1,1,2) != 5 || mat(2,1,2) != 6 || +// mat(0,2,2) != 7 || mat(1,2,2) != 8 || mat(2,2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Transpose operation failed\n" +// << " Details:\n" +// << " Result:\n" << mat << "\n" +// << " Expected result:\n" +// "(( 1 1 1 )\n( 4 4 4 )\n( 7 7 7 )\n" +// " ( 2 2 2 )\n( 5 5 5 )\n( 8 8 8 )\n" +// " ( 3 3 3 )\n( 6 6 6 )\n( 9 9 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Try to self-transpose a 2x3x5 tensor +// try { +// std::unique_ptr memory( blaze::allocate( 480UL ) ); +// MT mat( memory.get(), 2UL, 3UL, 5UL, 16UL ); +// +// transpose( mat ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Self-transpose of a non-square tensor succeeded\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::logic_error& ) {} +// } +// +// { +// test_ = "Row-major self-transpose via trans()"; +// +// // Self-transpose of a 3x3x3 tensor +// { +// std::unique_ptr memory( blaze::allocate( 432UL ) ); +// MT mat( memory.get(), 3UL, 3UL, 3UL, 16UL ); +// mat(0,0,0) = 1; +// mat(0,0,1) = 2; +// mat(0,0,2) = 3; +// mat(0,1,0) = 4; +// mat(0,1,1) = 5; +// mat(0,1,2) = 6; +// mat(0,2,0) = 7; +// mat(0,2,1) = 8; +// mat(0,2,2) = 9; +// mat(1,0,0) = 1; +// mat(1,0,1) = 2; +// mat(1,0,2) = 3; +// mat(1,1,0) = 4; +// mat(1,1,1) = 5; +// mat(1,1,2) = 6; +// mat(1,2,0) = 7; +// mat(1,2,1) = 8; +// mat(1,2,2) = 9; +// mat(2,0,0) = 1; +// mat(2,0,1) = 2; +// mat(2,0,2) = 3; +// mat(2,1,0) = 4; +// mat(2,1,1) = 5; +// mat(2,1,2) = 6; +// mat(2,2,0) = 7; +// mat(2,2,1) = 8; +// mat(2,2,2) = 9; +// +// mat = trans(mat, {2, 1, 0}); +// +// checkRows ( mat, 3UL ); +// checkColumns ( mat, 3UL ); +// checkPages ( mat, 3UL ); +// checkCapacity( mat, 27UL ); +// checkNonZeros( mat, 27UL ); +// checkNonZeros( mat, 0UL, 0UL, 3UL ); +// checkNonZeros( mat, 1UL, 0UL, 3UL ); +// checkNonZeros( mat, 2UL, 0UL, 3UL ); +// checkNonZeros( mat, 0UL, 1UL, 3UL ); +// checkNonZeros( mat, 1UL, 1UL, 3UL ); +// checkNonZeros( mat, 2UL, 1UL, 3UL ); +// checkNonZeros( mat, 0UL, 2UL, 3UL ); +// checkNonZeros( mat, 1UL, 2UL, 3UL ); +// checkNonZeros( mat, 2UL, 2UL, 3UL ); +// +// if( mat(0,0,0) != 1 || mat(1,0,0) != 2 || mat(2,0,0) != 3 || +// mat(0,1,0) != 4 || mat(1,1,0) != 5 || mat(2,1,0) != 6 || +// mat(0,2,0) != 7 || mat(1,2,0) != 8 || mat(2,2,0) != 9 || +// mat(0,0,1) != 1 || mat(1,0,1) != 2 || mat(2,0,1) != 3 || +// mat(0,1,1) != 4 || mat(1,1,1) != 5 || mat(2,1,1) != 6 || +// mat(0,2,1) != 7 || mat(1,2,1) != 8 || mat(2,2,1) != 9 || +// mat(0,0,2) != 1 || mat(1,0,2) != 2 || mat(2,0,2) != 3 || +// mat(0,1,2) != 4 || mat(1,1,2) != 5 || mat(2,1,2) != 6 || +// mat(0,2,2) != 7 || mat(1,2,2) != 8 || mat(2,2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Transpose operation failed\n" +// << " Details:\n" +// << " Result:\n" << mat << "\n" +// << " Expected result:\n" +// "(( 1 1 1 )\n( 4 4 4 )\n( 7 7 7 )\n" +// " ( 2 2 2 )\n( 5 5 5 )\n( 8 8 8 )\n" +// " ( 3 3 3 )\n( 6 6 6 )\n( 9 9 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Try to self-transpose a 2x3x5 tensor +// try { +// std::unique_ptr memory( blaze::allocate( 480UL ) ); +// MT mat( memory.get(), 2UL, 3UL, 5UL, 16UL ); +// +// mat = trans( mat ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Self-transpose of a non-square tensor succeeded\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::logic_error& ) {} +// } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c transpose() member function of the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c ctranspose() member function of the CustomArray +// class template. Additionally, it performs a test of self-transpose via the \c ctrans() +// function. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testCTranspose() +{ +// //===================================================================================== +// // Row-major tensor tests +// //===================================================================================== +// +// { +// test_ = "Row-major self-transpose via ctranspose()"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// using cplx = blaze::complex; +// using AlignedPadded = blaze::CustomArray<3,cplx,aligned,padded>; +// +// // Self-transpose of a 3x3 tensor +// { +// std::unique_ptr memory( blaze::allocate( 48UL ) ); +// AlignedPadded mat( memory.get(), 16UL, 3UL, 3UL ); +// mat(0,0) = cplx(1,-1); +// mat(0,1) = cplx(0, 0); +// mat(0,2) = cplx(2,-2); +// mat(1,0) = cplx(0, 0); +// mat(1,1) = cplx(3,-3); +// mat(1,2) = cplx(0, 0); +// mat(2,0) = cplx(4,-4); +// mat(2,1) = cplx(0, 0); +// mat(2,2) = cplx(5,-5); +// +// ctranspose( mat ); +// +// checkRows ( mat, 3UL ); +// checkColumns ( mat, 3UL ); +// checkCapacity( mat, 48UL ); +// checkNonZeros( mat, 5UL ); +// checkNonZeros( mat, 0UL, 2UL ); +// checkNonZeros( mat, 1UL, 1UL ); +// checkNonZeros( mat, 2UL, 2UL ); +// +// if( mat(0,0) != cplx(1,1) || mat(0,1) != cplx(0,0) || mat(0,2) != cplx(4,4) || +// mat(1,0) != cplx(0,0) || mat(1,1) != cplx(3,3) || mat(1,2) != cplx(0,0) || +// mat(2,0) != cplx(2,2) || mat(2,1) != cplx(0,0) || mat(2,2) != cplx(5,5) ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Initialization failed\n" +// << " Details:\n" +// << " Result:\n" << mat << "\n" +// << " Expected result:\n( (1,1) (0,0) (4,4) )\n" +// "( (0,0) (3,3) (0,0) )\n" +// "( (2,2) (0,0) (5,5) )\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Try to self-transpose a 3x5 tensor +// try { +// std::unique_ptr memory( blaze::allocate( 48UL ) ); +// AlignedPadded mat( memory.get(), 16UL, 3UL, 5UL ); +// +// ctranspose( mat ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Self-transpose of a non-square tensor succeeded\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::logic_error& ) {} +// } +// +// { +// test_ = "Row-major self-transpose via ctrans()"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// using cplx = blaze::complex; +// using AlignedPadded = blaze::CustomArray<3,cplx,aligned,padded>; +// +// // Self-transpose of a 3x3 tensor +// { +// std::unique_ptr memory( blaze::allocate( 48UL ) ); +// AlignedPadded mat( memory.get(), 16UL, 3UL, 3UL ); +// mat(0,0) = cplx(1,-1); +// mat(0,1) = cplx(0, 0); +// mat(0,2) = cplx(2,-2); +// mat(1,0) = cplx(0, 0); +// mat(1,1) = cplx(3,-3); +// mat(1,2) = cplx(0, 0); +// mat(2,0) = cplx(4,-4); +// mat(2,1) = cplx(0, 0); +// mat(2,2) = cplx(5,-5); +// +// mat = ctrans( mat ); +// +// checkRows ( mat, 3UL ); +// checkColumns ( mat, 3UL ); +// checkCapacity( mat, 48UL ); +// checkNonZeros( mat, 5UL ); +// checkNonZeros( mat, 0UL, 2UL ); +// checkNonZeros( mat, 1UL, 1UL ); +// checkNonZeros( mat, 2UL, 2UL ); +// +// if( mat(0,0) != cplx(1,1) || mat(0,1) != cplx(0,0) || mat(0,2) != cplx(4,4) || +// mat(1,0) != cplx(0,0) || mat(1,1) != cplx(3,3) || mat(1,2) != cplx(0,0) || +// mat(2,0) != cplx(2,2) || mat(2,1) != cplx(0,0) || mat(2,2) != cplx(5,5) ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Initialization failed\n" +// << " Details:\n" +// << " Result:\n" << mat << "\n" +// << " Expected result:\n( (1,1) (0,0) (4,4) )\n" +// "( (0,0) (3,3) (0,0) )\n" +// "( (2,2) (0,0) (5,5) )\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Try to self-transpose a 3x5 tensor +// try { +// std::unique_ptr memory( blaze::allocate( 48UL ) ); +// AlignedPadded mat( memory.get(), 16UL, 3UL, 5UL ); +// +// mat = ctrans( mat ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Self-transpose of a non-square tensor succeeded\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isDefault() function with the CustomArray class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c isDefault() function with the CustomArray class +// template. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void AlignedPaddedTest::testIsDefault() +{ + using blaze::isDefault; + + + //===================================================================================== + // Row-major tensor tests + //===================================================================================== + + { + test_ = "Row-major isDefault() function"; + + // isDefault with 0x0 tensor + { + MT mat; + + if( isDefault( mat ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " Matrix:\n" << mat << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isDefault with default tensor + { + std::unique_ptr memory( blaze::allocate( 64UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + reset( mat ); + + if( isDefault( mat(0,0,1) ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " Matrix element: " << mat(0,0,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( isDefault( mat ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " Matrix:\n" << mat << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isDefault with non-default tensor + { + std::unique_ptr memory( blaze::allocate( 128UL ) ); + MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); + reset( mat ); + mat(1,0,1) = 1; + + if( isDefault( mat(1,0,1) ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " Matrix element: " << mat(1,0,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( isDefault( mat ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " Matrix:\n" << mat << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + +} // namespace customarray + +} // namespace mathtest + +} // namespace blazetest + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + std::cout << " Running aligned/padded CustomArray class test (part 2)..." << std::endl; + + try + { + RUN_CUSTOMARRAY_ALIGNED_PADDED_TEST; + } + catch( std::exception& ex ) { + std::cerr << "\n\n ERROR DETECTED during aligned/padded CustomArray class test (part 2):\n" + << ex.what() << "\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +//************************************************************************************************* diff --git a/blazetest/src/mathtest/customarray/CMakeLists.txt b/blazetest/src/mathtest/customarray/CMakeLists.txt new file mode 100644 index 0000000..302a7bb --- /dev/null +++ b/blazetest/src/mathtest/customarray/CMakeLists.txt @@ -0,0 +1,45 @@ +# ================================================================================================= +# +# Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +# Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +# +# This file is part of the Blaze library. You can redistribute it and/or modify it under +# the terms of the New (Revised) BSD License. Redistribution and use in source and binary +# forms, with or without modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# 3. Neither the names of the Blaze development group nor the names of its contributors +# may be used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# ================================================================================================= + +set(category CustomArray) + +set(tests + AlignedPaddedTest1 + AlignedPaddedTest2 + IncludeTest +) + +foreach(test ${tests}) + add_blaze_tensor_test(${category}${test} + SOURCES ${test}.cpp + FOLDER "Tests/${category}") +endforeach() diff --git a/blazetest/src/mathtest/customarray/IncludeTest.cpp b/blazetest/src/mathtest/customarray/IncludeTest.cpp new file mode 100644 index 0000000..6c90e69 --- /dev/null +++ b/blazetest/src/mathtest/customarray/IncludeTest.cpp @@ -0,0 +1,61 @@ +//================================================================================================= +/*! +// \file src/mathtest/customarray/IncludeTest.cpp +// \brief Source file for the CustomArray include test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + return EXIT_SUCCESS; +} +//************************************************************************************************* From 81baba0dcee1ae9da2112d3ed94fd7e9f4ae774e Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 31 May 2019 19:14:08 -0500 Subject: [PATCH 06/14] More work on ArraySlice --- blaze_tensor/math/dense/CustomArray.h | 43 +- blaze_tensor/math/dense/DynamicArray.h | 506 +++++++++++++++++- .../math/views/arrayslice/ArraySlice.h | 238 ++++---- blaze_tensor/math/views/arrayslice/Dense.h | 192 +++++++ .../mathtest/arrayslice/DenseGeneralTest.cpp | 33 +- 5 files changed, 866 insertions(+), 146 deletions(-) diff --git a/blaze_tensor/math/dense/CustomArray.h b/blaze_tensor/math/dense/CustomArray.h index 7e7c5f8..1ad1467 100644 --- a/blaze_tensor/math/dense/CustomArray.h +++ b/blaze_tensor/math/dense/CustomArray.h @@ -482,6 +482,33 @@ class CustomArray template< typename MT > inline CustomArray& operator+=( const Array& rhs ); template< typename MT > inline CustomArray& operator-=( const Array& rhs ); template< typename MT > inline CustomArray& operator%=( const Array& rhs ); + + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline ArraySlice& operator= ( const Vector& m ); + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline ArraySlice& operator+=( const Vector& m ); + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline ArraySlice& operator-=( const Vector& m ); + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline ArraySlice& operator%=( const Vector& m ); + + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline ArraySlice& operator= ( const Matrix& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline ArraySlice& operator+=( const Matrix& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline ArraySlice& operator-=( const Matrix& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline ArraySlice& operator%=( const Matrix& m ); + + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline ArraySlice& operator= ( const Tensor& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline ArraySlice& operator+=( const Tensor& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline ArraySlice& operator-=( const Tensor& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline ArraySlice& operator%=( const Tensor& m ); //@} //********************************************************************************************** @@ -1669,6 +1696,10 @@ template< typename MT > // Type of the right-hand side array inline CustomArray& CustomArray::operator=( const Array& rhs ) { + if( dims_ != (~rhs).dimensions() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + if( (~rhs).canAlias( this ) ) { const ResultType_t tmp( ~rhs ); smpAssign( *this, tmp ); @@ -1701,9 +1732,7 @@ template< typename MT > // Type of the right-hand side array inline CustomArray& CustomArray::operator+=( const Array& rhs ) { - auto rhsdims = (~rhs).dimensions(); - if( ArrayDimAnyOf( dims_, - [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + if( dims_ != (~rhs).dimensions() ) { BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); } @@ -1739,9 +1768,7 @@ template< typename MT > // Type of the right-hand side array inline CustomArray& CustomArray::operator-=( const Array& rhs ) { - auto rhsdims = (~rhs).dimensions(); - if( ArrayDimAnyOf( dims_, - [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + if( dims_ != (~rhs).dimensions() ) { BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); } @@ -1777,9 +1804,7 @@ template< typename MT > // Type of the right-hand side array inline CustomArray& CustomArray::operator%=( const Array& rhs ) { - auto rhsdims = (~rhs).dimensions(); - if( ArrayDimAnyOf( dims_, - [&]( size_t i, size_t dim ) { return rhsdims[i] != dim; } ) ) { + if( dims_ != (~rhs).dimensions() ) { BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); } diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index f5b5834..2ddeb01 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -209,7 +209,14 @@ class DynamicArray inline DynamicArray( const DynamicArray& m ); inline DynamicArray( DynamicArray&& m ) noexcept; - template< typename MT> inline DynamicArray( const Array& m ); + template< typename MT > inline DynamicArray( const Array& m ); + + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline DynamicArray( const Vector& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline DynamicArray( const Matrix& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline DynamicArray( const Tensor& m ); //@} //********************************************************************************************** @@ -269,6 +276,33 @@ class DynamicArray template< typename MT > inline DynamicArray& operator+=( const Array& rhs ); template< typename MT > inline DynamicArray& operator-=( const Array& rhs ); template< typename MT > inline DynamicArray& operator%=( const Array& rhs ); + + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline DynamicArray& operator= ( const Vector& m ); + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline DynamicArray& operator+=( const Vector& m ); + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline DynamicArray& operator-=( const Vector& m ); + template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + inline DynamicArray& operator%=( const Vector& m ); + + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline DynamicArray& operator= ( const Matrix& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline DynamicArray& operator+=( const Matrix& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline DynamicArray& operator-=( const Matrix& m ); + template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + inline DynamicArray& operator%=( const Matrix& m ); + + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline DynamicArray& operator= ( const Tensor& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline DynamicArray& operator+=( const Tensor& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline DynamicArray& operator-=( const Tensor& m ); + template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + inline DynamicArray& operator%=( const Tensor& m ); //@} //********************************************************************************************** @@ -690,6 +724,90 @@ inline DynamicArray::DynamicArray( const Array& rhs ) //************************************************************************************************* +//************************************************************************************************* +/*!\brief Conversion constructor from different arrays. +// +// \param m Array to be copied. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool TF, size_t M, typename Enable > +inline DynamicArray::DynamicArray( const Vector& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<1, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief Conversion constructor from different arrays. +// +// \param m Array to be copied. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool SO, size_t M, typename Enable > +inline DynamicArray::DynamicArray( const Matrix& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<2, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief Conversion constructor from different arrays. +// +// \param m Array to be copied. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, size_t M, typename Enable > +inline DynamicArray::DynamicArray( const Tensor& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<2, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); +} +//************************************************************************************************* + //************************************************************************************************* /*!\brief Constructor from array bounds. // @@ -1465,6 +1583,392 @@ inline DynamicArray& DynamicArray::operator%=( const Array //************************************************************************************************* +//************************************************************************************************* +/*!\brief Homogeneous assignment to all array elements. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool TF, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator=( const Vector& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<1, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Addition assignment operator for the addition of a array (\f$ A+=B \f$). +// +// \param rhs The right-hand side array to be added to the array. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool TF, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator+=( const Vector& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<1, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAddAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAddAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Subtraction assignment operator for the subtraction of a array (\f$ A-=B \f$). +// +// \param rhs The right-hand side array to be subtracted from the array. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool TF, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator-=( const Vector& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<1, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSubAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpSubAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Schur product assignment operator for the multiplication of a array (\f$ A\circ=B \f$). +// +// \param rhs The right-hand side array for the Schur product. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool TF, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator%=( const Vector& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<1, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSchurAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpSchurAssign( *this, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Homogeneous assignment to all array elements. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool SO, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator=( const Matrix& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<2, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Addition assignment operator for the addition of a array (\f$ A+=B \f$). +// +// \param rhs The right-hand side array to be added to the array. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool SO, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator+=( const Matrix& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<2, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAddAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAddAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Subtraction assignment operator for the subtraction of a array (\f$ A-=B \f$). +// +// \param rhs The right-hand side array to be subtracted from the array. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool SO, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator-=( const Matrix& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<2, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSubAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpSubAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Schur product assignment operator for the multiplication of a array (\f$ A\circ=B \f$). +// +// \param rhs The right-hand side array for the Schur product. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, bool SO, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator%=( const Matrix& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<2, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSchurAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpSchurAssign( *this, + custom_array( tmp.data(), tmp.rows(), tmp.columns(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Homogeneous assignment to all array elements. +// +// \param rhs Array to be copied. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator=( const Tensor& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<3, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Addition assignment operator for the subtraction of a array (\f$ A+=B \f$). +// +// \param rhs The right-hand side array to be added to the array. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator+=( const Tensor& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<3, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpAddAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpAddAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Subtraction assignment operator for the subtraction of a array (\f$ A-=B \f$). +// +// \param rhs The right-hand side array to be subtracted from the array. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator-=( const Tensor& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<3, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSubAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpSubAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Schur product assignment operator for the multiplication of a array (\f$ A\circ=B \f$). +// +// \param rhs The right-hand side array for the Schur product. +// \return Reference to the assigned array. +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +template< typename MT, size_t M, typename Enable > +inline DynamicArray& DynamicArray::operator%=( const Tensor& rhs ) +{ + using ET = ElementType_t; + using custom_array = CustomArray<3, ET, false, true>; + + if( (~rhs).canAlias( this ) ) { + const ResultType_t tmp( ~rhs ); + smpSchurAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + else { + auto const& tmp = ~rhs; + smpSchurAssign( *this, + custom_array( tmp.data(), tmp.pages(), tmp.rows(), tmp.columns(), + tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" ); + + return *this; +} +//************************************************************************************************* + + + + //================================================================================================= diff --git a/blaze_tensor/math/views/arrayslice/ArraySlice.h b/blaze_tensor/math/views/arrayslice/ArraySlice.h index f0ddff4..6a55cbc 100644 --- a/blaze_tensor/math/views/arrayslice/ArraySlice.h +++ b/blaze_tensor/math/views/arrayslice/ArraySlice.h @@ -1,10 +1,10 @@ //================================================================================================= /*! -// \file blaze_tensor/math/views/pageslice/PageSlice.h +// \file blaze_tensor/math/views/arrayslice/PageSlice.h // \brief PageSlice documentation // // Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved // // This file is part of the Blaze library. You can redistribute it and/or modify it under // the terms of the New (Revised) BSD License. Redistribution and use in source and binary @@ -33,8 +33,8 @@ */ //================================================================================================= -#ifndef _BLAZE_TENSOR_MATH_VIEWS_PAGESLICE_PAGESLICE_H_ -#define _BLAZE_TENSOR_MATH_VIEWS_PAGESLICE_PAGESLICE_H_ +#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICE_H_ //================================================================================================= @@ -44,57 +44,57 @@ //================================================================================================= //************************************************************************************************* -/*!\defgroup pageslice PageSlice +/*!\defgroup arrayslice PageSlice // \ingroup views // -// PageSlices provide views on a specific pageslice of a dense or sparse tensor. As such, pageslices act as a -// reference to a specific pageslice. This reference is valid and can be used in every way any other -// pageslice matrix can be used as long as the tensor containing the pageslice is not resized or entirely -// destroyed. The pageslice also acts as an alias to the pageslice elements: Changes made to the elements +// PageSlices provide views on a specific arrayslice of a dense or sparse tensor. As such, arrayslices act as a +// reference to a specific arrayslice. This reference is valid and can be used in every way any other +// arrayslice matrix can be used as long as the tensor containing the arrayslice is not resized or entirely +// destroyed. The arrayslice also acts as an alias to the arrayslice elements: Changes made to the elements // (e.g. modifying values, inserting or erasing elements) are immediately visible in the tensor -// and changes made via the tensor are immediately visible in the pageslice. +// and changes made via the tensor are immediately visible in the arrayslice. // // -// \n \section pageslice_setup Setup of PageSlices +// \n \section arrayslice_setup Setup of PageSlices // -// \image html pageslice.png -// \image latex pageslice.eps "PageSlice view" width=250pt +// \image html arrayslice.png +// \image latex arrayslice.eps "PageSlice view" width=250pt // -// A reference to a dense or sparse pageslice can be created very conveniently via the \c pageslice() function. +// A reference to a dense or sparse arrayslice can be created very conveniently via the \c arrayslice() function. // It can be included via the header file \code #include \endcode -// The pageslice index must be in the range from \f$[0..M-1]\f$, where \c M is the total number of pageslices +// The arrayslice index must be in the range from \f$[0..M-1]\f$, where \c M is the total number of arrayslices // of the tensor, and can be specified both at compile time or at runtime: \code blaze::DynamicTensor A; // ... Resizing and initialization - // Creating a reference to the 1st pageslice of tensor A (compile time index) - auto pageslice1 = pageslice<1UL>( A ); + // Creating a reference to the 1st arrayslice of tensor A (compile time index) + auto arrayslice1 = arrayslice<1UL>( A ); - // Creating a reference to the 2nd pageslice of tensor A (runtime index) - auto pageslice2 = pageslice( A, 2UL ); + // Creating a reference to the 2nd arrayslice of tensor A (runtime index) + auto arrayslice2 = arrayslice( A, 2UL ); \endcode -// The \c pageslice() function returns an expression representing the pageslice view. The type of this -// expression depends on the given pageslice arguments, primarily the type of the tensor and the compile +// The \c arrayslice() function returns an expression representing the arrayslice view. The type of this +// expression depends on the given arrayslice arguments, primarily the type of the tensor and the compile // time arguments. If the type is required, it can be determined via \c decltype specifier: \code using TensorType = blaze::DynamicTensor; - using PageSliceType = decltype( blaze::pageslice<1UL>( std::declval() ) ); + using PageSliceType = decltype( blaze::arrayslice<1UL>( std::declval() ) ); \endcode -// The resulting view can be treated as any other pageslice matrix, i.e. it can be assigned to, it can +// The resulting view can be treated as any other arrayslice matrix, i.e. it can be assigned to, it can // be copied from, and it can be used in arithmetic operations. The reference can also be used on -// both sides of an assignment: The pageslice can either be used as an alias to grant write access to a -// specific pageslice of a tensor primitive on the left-hand side of an assignment or to grant read-access -// to a specific pageslice of a tensor primitive or expression on the right-hand side of an assignment. +// both sides of an assignment: The arrayslice can either be used as an alias to grant write access to a +// specific arrayslice of a tensor primitive on the left-hand side of an assignment or to grant read-access +// to a specific arrayslice of a tensor primitive or expression on the right-hand side of an assignment. // The following example demonstrates this in detail: \code @@ -102,61 +102,61 @@ blaze::DynamicTensor A, B; // ... Resizing and initialization - // Setting the 2nd pageslice of tensor A to x - auto pageslice2 = pageslice( A, 2UL ); - pageslice2 = x; + // Setting the 2nd arrayslice of tensor A to x + auto arrayslice2 = arrayslice( A, 2UL ); + arrayslice2 = x; - // Setting the 3rd pageslice of tensor B to x - pageslice( B, 3UL ) = x; + // Setting the 3rd arrayslice of tensor B to x + arrayslice( B, 3UL ) = x; - // Setting x to the 4th pageslice of the result of the tensor multiplication - x = pageslice( A * B, 4UL ); + // Setting x to the 4th arrayslice of the result of the tensor multiplication + x = arrayslice( A * B, 4UL ); \endcode -// \n \section pageslice_element_access Element access +// \n \section arrayslice_element_access Element access // -// The elements of a pageslice can be directly accessed with the subscript operator: +// The elements of a arrayslice can be directly accessed with the subscript operator: \code blaze::DynamicTensor A; // ... Resizing and initialization - // Creating a view on the 4th pageslice of tensor A - auto pageslice4 = pageslice( A, 4UL ); + // Creating a view on the 4th arrayslice of tensor A + auto arrayslice4 = arrayslice( A, 4UL ); - // Setting the 1st element of the dense pageslice, which corresponds - // to the 1st element in the 4th pageslice of tensor A - pageslice4(0, 0) = 2.0; + // Setting the 1st element of the dense arrayslice, which corresponds + // to the 1st element in the 4th arrayslice of tensor A + arrayslice4(0, 0) = 2.0; \endcode -// The numbering of the pageslice elements is +// The numbering of the arrayslice elements is \f[\left(\begin{array}{*{5}{c}} 0 & 1 & 2 & \cdots & N-1 \\ \end{array}\right),\f] // where N is the number of columns of the referenced tensor. Alternatively, the elements of a -// pageslice can be traversed via iterators. Just as with vectors, in case of non-const pageslices, \c begin() +// arrayslice can be traversed via iterators. Just as with vectors, in case of non-const arrayslices, \c begin() // and \c end() return an iterator, which allows to manipulate the elements, in case of constant -// pageslices an iterator to immutable elements is returned: +// arrayslices an iterator to immutable elements is returned: \code blaze::DynamicTensor A( 128UL, 256UL ); // ... Resizing and initialization - // Creating a reference to the 31st pageslice of tensor A - auto pageslice31 = pageslice( A, 31UL ); + // Creating a reference to the 31st arrayslice of tensor A + auto arrayslice31 = arrayslice( A, 31UL ); // Traversing the elements via iterators to non-const elements - for( auto it=pageslice31.begin(); it!=pageslice31.end(); ++it ) { - *it = ...; // OK; Write access to the dense pageslice value - ... = *it; // OK: Read access to the dense pageslice value. + for( auto it=arrayslice31.begin(); it!=arrayslice31.end(); ++it ) { + *it = ...; // OK; Write access to the dense arrayslice value + ... = *it; // OK: Read access to the dense arrayslice value. } // Traversing the elements via iterators to const elements - for( auto it=pageslice31.cbegin(); it!=pageslice31.cend(); ++it ) { + for( auto it=arrayslice31.cbegin(); it!=arrayslice31.cend(); ++it ) { *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. - ... = *it; // OK: Read access to the dense pageslice value. + ... = *it; // OK: Read access to the dense arrayslice value. } \endcode @@ -164,11 +164,11 @@ blaze::CompressedMatrix A( 128UL, 256UL ); // ... Resizing and initialization - // Creating a reference to the 31st pageslice of tensor A - auto pageslice31 = pageslice( A, 31UL ); + // Creating a reference to the 31st arrayslice of tensor A + auto arrayslice31 = arrayslice( A, 31UL ); // Traversing the elements via iterators to non-const elements - for( auto it=pageslice31.begin(); it!=pageslice31.end(); ++it ) { + for( auto it=arrayslice31.begin(); it!=arrayslice31.end(); ++it ) { it->value() = ...; // OK: Write access to the value of the non-zero element. ... = it->value(); // OK: Read access to the value of the non-zero element. it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. @@ -176,7 +176,7 @@ } // Traversing the elements via iterators to const elements - for( auto it=pageslice31.cbegin(); it!=pageslice31.cend(); ++it ) { + for( auto it=arrayslice31.cbegin(); it!=arrayslice31.cend(); ++it ) { it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. ... = it->value(); // OK: Read access to the value of the non-zero element. it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. @@ -184,69 +184,69 @@ } \endcode -// \n \section sparse_pageslice_element_insertion Element Insertion +// \n \section sparse_arrayslice_element_insertion Element Insertion // -// Inserting/accessing elements in a sparse pageslice can be done by several alternative functions. +// Inserting/accessing elements in a sparse arrayslice can be done by several alternative functions. // The following example demonstrates all options: \code blaze::CompressedMatrix A( 10UL, 100UL ); // Non-initialized 10x100 tensor - auto pageslice0( pageslice( A, 0UL ) ); // Reference to the 0th pageslice of A + auto arrayslice0( arrayslice( A, 0UL ) ); // Reference to the 0th arrayslice of A - // The subscript operator provides access to all possible elements of the sparse pageslice, + // The subscript operator provides access to all possible elements of the sparse arrayslice, // including the zero elements. In case the subscript operator is used to access an element - // that is currently not stored in the sparse pageslice, the element is inserted into the pageslice. - pageslice0[42] = 2.0; + // that is currently not stored in the sparse arrayslice, the element is inserted into the arrayslice. + arrayslice0[42] = 2.0; // The second operation for inserting elements is the set() function. In case the element - // is not contained in the pageslice it is inserted into the pageslice, if it is already contained in - // the pageslice its value is modified. - pageslice0.set( 45UL, -1.2 ); + // is not contained in the arrayslice it is inserted into the arrayslice, if it is already contained in + // the arrayslice its value is modified. + arrayslice0.set( 45UL, -1.2 ); - // An alternative for inserting elements into the pageslice is the insert() function. However, - // it inserts the element only in case the element is not already contained in the pageslice. - pageslice0.insert( 50UL, 3.7 ); + // An alternative for inserting elements into the arrayslice is the insert() function. However, + // it inserts the element only in case the element is not already contained in the arrayslice. + arrayslice0.insert( 50UL, 3.7 ); - // A very efficient way to add new elements to a sparse pageslice is the append() function. + // A very efficient way to add new elements to a sparse arrayslice is the append() function. // Note that append() requires that the appended element's index is strictly larger than - // the currently largest non-zero index of the pageslice and that the pageslice's capacity is large + // the currently largest non-zero index of the arrayslice and that the arrayslice's capacity is large // enough to hold the new element. - pageslice0.reserve( 10UL ); - pageslice0.append( 51UL, -2.1 ); + arrayslice0.reserve( 10UL ); + arrayslice0.append( 51UL, -2.1 ); \endcode -// \n \section pageslice_common_operations Common Operations +// \n \section arrayslice_common_operations Common Operations // -// A pageslice view can be used like any other pageslice vector. For instance, the current number of pageslice +// A arrayslice view can be used like any other arrayslice vector. For instance, the current number of arrayslice // elements can be obtained via the \c size() function, the current capacity via the \c capacity() // function, and the number of non-zero elements via the \c nonZeros() function. However, since -// pageslices are references to specific pageslices of a tensor, several operations are not possible, such as -// resizing and swapping. The following example shows this by means of a dense pageslice view: +// arrayslices are references to specific arrayslices of a tensor, several operations are not possible, such as +// resizing and swapping. The following example shows this by means of a dense arrayslice view: \code blaze::DynamicTensor A( 42UL, 42UL ); // ... Resizing and initialization - // Creating a reference to the 2nd pageslice of tensor A - auto pageslice2 = pageslice( A, 2UL ); + // Creating a reference to the 2nd arrayslice of tensor A + auto arrayslice2 = arrayslice( A, 2UL ); - pageslice2.size(); // Returns the number of elements in the pageslice - pageslice2.capacity(); // Returns the capacity of the pageslice - pageslice2.nonZeros(); // Returns the number of non-zero elements contained in the pageslice + arrayslice2.size(); // Returns the number of elements in the arrayslice + arrayslice2.capacity(); // Returns the capacity of the arrayslice + arrayslice2.nonZeros(); // Returns the number of non-zero elements contained in the arrayslice - pageslice2.resize( 84UL ); // Compilation error: Cannot resize a single pageslice of a tensor + arrayslice2.resize( 84UL ); // Compilation error: Cannot resize a single arrayslice of a tensor - auto pageslice3 = pageslice( A, 3UL ); - swap( pageslice2, pageslice3 ); // Compilation error: Swap operation not allowed + auto arrayslice3 = arrayslice( A, 3UL ); + swap( arrayslice2, arrayslice3 ); // Compilation error: Swap operation not allowed \endcode -// \n \section pageslice_arithmetic_operations Arithmetic Operations +// \n \section arrayslice_arithmetic_operations Arithmetic Operations // -// Both dense and sparse pageslices can be used in all arithmetic operations that any other dense or -// sparse pageslice vector can be used in. The following example gives an impression of the use of -// dense pageslices within arithmetic operations. All operations (addition, subtraction, multiplication, -// scaling, ...) can be performed on all possible combinations of dense and sparse pageslices with +// Both dense and sparse arrayslices can be used in all arithmetic operations that any other dense or +// sparse arrayslice vector can be used in. The following example gives an impression of the use of +// dense arrayslices within arithmetic operations. All operations (addition, subtraction, multiplication, +// scaling, ...) can be performed on all possible combinations of dense and sparse arrayslices with // fitting element types: \code @@ -256,54 +256,54 @@ blaze::DynamicTensor A( 4UL, 2UL ); // Non-initialized 4x2 tensor - auto pageslice0( pageslice( A, 0UL ) ); // Reference to the 0th pageslice of A + auto arrayslice0( arrayslice( A, 0UL ) ); // Reference to the 0th arrayslice of A - pageslice0[0] = 0.0; // Manual initialization of the 0th pageslice of A - pageslice0[1] = 0.0; - pageslice( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st pageslice of A - pageslice( A, 2UL ) = a; // Dense vector initialization of the 2nd pageslice of A - pageslice( A, 3UL ) = c; // Sparse vector initialization of the 3rd pageslice of A + arrayslice0[0] = 0.0; // Manual initialization of the 0th arrayslice of A + arrayslice0[1] = 0.0; + arrayslice( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st arrayslice of A + arrayslice( A, 2UL ) = a; // Dense vector initialization of the 2nd arrayslice of A + arrayslice( A, 3UL ) = c; // Sparse vector initialization of the 3rd arrayslice of A - b = pageslice0 + a; // Dense vector/dense vector addition - b = c + pageslice( A, 1UL ); // Sparse vector/dense vector addition - b = pageslice0 * pageslice( A, 2UL ); // Component-wise vector multiplication + b = arrayslice0 + a; // Dense vector/dense vector addition + b = c + arrayslice( A, 1UL ); // Sparse vector/dense vector addition + b = arrayslice0 * arrayslice( A, 2UL ); // Component-wise vector multiplication - pageslice( A, 1UL ) *= 2.0; // In-place scaling of the 1st pageslice - b = pageslice( A, 1UL ) * 2.0; // Scaling of the 1st pageslice - b = 2.0 * pageslice( A, 1UL ); // Scaling of the 1st pageslice + arrayslice( A, 1UL ) *= 2.0; // In-place scaling of the 1st arrayslice + b = arrayslice( A, 1UL ) * 2.0; // Scaling of the 1st arrayslice + b = 2.0 * arrayslice( A, 1UL ); // Scaling of the 1st arrayslice - pageslice( A, 2UL ) += a; // Addition assignment - pageslice( A, 2UL ) -= c; // Subtraction assignment - pageslice( A, 2UL ) *= pageslice( A, 0UL ); // Multiplication assignment + arrayslice( A, 2UL ) += a; // Addition assignment + arrayslice( A, 2UL ) -= c; // Subtraction assignment + arrayslice( A, 2UL ) *= arrayslice( A, 0UL ); // Multiplication assignment - double scalar = pageslice( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors + double scalar = arrayslice( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors - A = trans( c ) * pageslice( A, 1UL ); // Outer product between two vectors + A = trans( c ) * arrayslice( A, 1UL ); // Outer product between two vectors \endcode -// \n \section pageslice_on_column_major_tensor PageSlices on Column-Major Matrices +// \n \section arrayslice_on_column_major_tensor PageSlices on Column-Major Matrices // -// Especially noteworthy is that pageslice views can be created for both pageslice-major and column-major -// matrices. Whereas the interface of a pageslice-major tensor only allows to traverse a pageslice directly +// Especially noteworthy is that arrayslice views can be created for both arrayslice-major and column-major +// matrices. Whereas the interface of a arrayslice-major tensor only allows to traverse a arrayslice directly // and the interface of a column-major tensor only allows to traverse a column, via views it is -// possible to traverse a pageslice of a column-major tensor or a column of a pageslice-major tensor. For +// possible to traverse a arrayslice of a column-major tensor or a column of a arrayslice-major tensor. For // instance: \code blaze::DynamicTensor A( 64UL, 32UL ); // ... Resizing and initialization - // Creating a reference to the 1st pageslice of a column-major tensor A - auto pageslice1 = pageslice( A, 1UL ); + // Creating a reference to the 1st arrayslice of a column-major tensor A + auto arrayslice1 = arrayslice( A, 1UL ); - for( auto it=pageslice1.begin(); it!=pageslice1.end(); ++it ) { + for( auto it=arrayslice1.begin(); it!=arrayslice1.end(); ++it ) { // ... } \endcode -// However, please note that creating a pageslice view on a tensor stored in a column-major fashion -// can result in a considerable performance decrease in comparison to a pageslice view on a tensor -// with pageslice-major storage format. This is due to the non-contiguous storage of the tensor +// However, please note that creating a arrayslice view on a tensor stored in a column-major fashion +// can result in a considerable performance decrease in comparison to a arrayslice view on a tensor +// with arrayslice-major storage format. This is due to the non-contiguous storage of the tensor // elements. Therefore care has to be taken in the choice of the most suitable storage order: \code @@ -312,16 +312,16 @@ blaze::DynamicTensor B( 128UL, 128UL ); // ... Resizing and initialization - // The computation of the 15th pageslice of the multiplication between A and B ... - blaze::DynamicVector x = pageslice( A * B, 15UL ); + // The computation of the 15th arrayslice of the multiplication between A and B ... + blaze::DynamicVector x = arrayslice( A * B, 15UL ); // ... is essentially the same as the following computation, which multiplies - // the 15th pageslice of the column-major tensor A with B. - blaze::DynamicVector x = pageslice( A, 15UL ) * B; + // the 15th arrayslice of the column-major tensor A with B. + blaze::DynamicVector x = arrayslice( A, 15UL ) * B; \endcode // Although Blaze performs the resulting vector/tensor multiplication as efficiently as possible -// using a pageslice-major storage order for tensor \c A would result in a more efficient evaluation. +// using a arrayslice-major storage order for tensor \c A would result in a more efficient evaluation. */ //************************************************************************************************* diff --git a/blaze_tensor/math/views/arrayslice/Dense.h b/blaze_tensor/math/views/arrayslice/Dense.h index b0ffb8a..0ca643b 100644 --- a/blaze_tensor/math/views/arrayslice/Dense.h +++ b/blaze_tensor/math/views/arrayslice/Dense.h @@ -228,6 +228,33 @@ class ArraySlice template< typename MT2 > inline ArraySlice& operator+=( const Array& rhs ); template< typename MT2 > inline ArraySlice& operator-=( const Array& rhs ); template< typename MT2 > inline ArraySlice& operator%=( const Array& rhs ); + + template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > + inline ArraySlice& operator= ( const Vector& m ); + template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > + inline ArraySlice& operator+=( const Vector& m ); + template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > + inline ArraySlice& operator-=( const Vector& m ); + template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > + inline ArraySlice& operator%=( const Vector& m ); + + template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > + inline ArraySlice& operator= ( const Matrix& m ); + template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > + inline ArraySlice& operator+=( const Matrix& m ); + template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > + inline ArraySlice& operator-=( const Matrix& m ); + template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > + inline ArraySlice& operator%=( const Matrix& m ); + + template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > + inline ArraySlice& operator= ( const Tensor& m ); + template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > + inline ArraySlice& operator+=( const Tensor& m ); + template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > + inline ArraySlice& operator-=( const Tensor& m ); + template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > + inline ArraySlice& operator%=( const Tensor& m ); //@} //********************************************************************************************** @@ -1164,6 +1191,171 @@ inline ArraySlice& //************************************************************************************************* +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Assignment operator for different matrices. +// +// \param rhs Array to be assigned. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Array sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2, bool TF, size_t M2, typename Enable > // Type of the right-hand side vector +inline ArraySlice& + ArraySlice::operator=( const Vector& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( dimension<0>() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; + Right right( ~rhs ); + + decltype(auto) left( derestrict( *this ) ); + + using ET = ElementType_t; + using custom_array = CustomArray<1, ET, false, true>; + + if( IsReference_v && right.canAlias( &array_ ) ) { + const ResultType_t tmp( right ); + smpAssign( left, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + else { + if( IsSparseArray_v ) + reset(); + auto const& tmp = right; + smpAssign( left, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Assignment operator for different matrices. +// +// \param rhs Array to be assigned. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Array sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2, bool SO, size_t M2, typename Enable > // Type of the right-hand side matrix +inline ArraySlice& + ArraySlice::operator=( const Matrix& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; + Right right( ~rhs ); + + if( !tryAssign( array_, right, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &array_ ) ) { + const ResultType_t tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseArray_v ) + reset(); + smpAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Assignment operator for different matrices. +// +// \param rhs Array to be assigned. +// \return Reference to the assigned arrayslice. +// \exception std::invalid_argument Array sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted array. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t M // Dimension of the ArraysSlice + , typename MT // Type of the dense array + , size_t... CRAs > // Compile time arrayslice arguments +template< typename MT2, size_t M2, typename Enable > // Type of the right-hand side tensor +inline ArraySlice& + ArraySlice::operator=( const Tensor& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; + Right right( ~rhs ); + + if( !tryAssign( array_, right, 0UL, 0UL, page() ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &array_ ) ) { + const ResultType_t tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseArray_v ) + reset(); + smpAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + //================================================================================================= diff --git a/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp index 8c34c14..ffdc5f1 100644 --- a/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp +++ b/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp @@ -1399,8 +1399,8 @@ void DenseGeneralTest::testMultAssign() initialize(); - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); arrayslice2 *= blaze::arrayslice<2>( m, 0UL ); @@ -1457,8 +1457,8 @@ void DenseGeneralTest::testMultAssign() initialize(); - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); @@ -1516,12 +1516,11 @@ void DenseGeneralTest::testMultAssign() using blaze::padded; using blaze::rowMajor; - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - using AlignedPadded = blaze::CustomMatrix; std::unique_ptr memory( blaze::allocate( 48UL ) ); AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); @@ -1586,8 +1585,8 @@ void DenseGeneralTest::testMultAssign() using blaze::unpadded; using blaze::rowMajor; - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); @@ -1669,8 +1668,8 @@ void DenseGeneralTest::testSchurAssign() { test_ = "ArraySlice Schur product assignment"; - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); arrayslice2 %= blaze::arrayslice<2>( m, 0UL ); @@ -1725,8 +1724,8 @@ void DenseGeneralTest::testSchurAssign() { test_ = "dense vector Schur product assignment (mixed type)"; - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); @@ -1784,8 +1783,8 @@ void DenseGeneralTest::testSchurAssign() using blaze::padded; using blaze::rowMajor; - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); @@ -1853,8 +1852,8 @@ void DenseGeneralTest::testSchurAssign() using blaze::unpadded; using blaze::rowMajor; - blaze::DynamicArray<3, int> m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); From d6672d144aa2ff2bfdd851e780467ee949fadc8e Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Fri, 28 Jun 2019 13:23:16 -0500 Subject: [PATCH 07/14] working toward developing quatslice --- blaze_tensor/math/Constraints.h | 1 + blaze_tensor/math/QuatSlice.h | 156 ++ blaze_tensor/math/Views.h | 1 + blaze_tensor/math/constraints/QuatSlice.h | 89 + .../math/constraints/QuatSliceTensor.h | 89 + blaze_tensor/math/dense/DynamicTensor.h | 51 +- blaze_tensor/math/smp/DenseArray.h | 2 +- blaze_tensor/math/traits/QuatSliceTrait.h | 208 ++ blaze_tensor/math/typetraits/IsQuatSlice.h | 169 ++ .../math/typetraits/IsQuatSliceTensor.h | 135 ++ blaze_tensor/math/views/QuatSlice.h | 1631 +++++++++++++ .../math/views/quatslice/BaseTemplate.h | 123 + blaze_tensor/math/views/quatslice/Dense.h | 2050 +++++++++++++++++ blaze_tensor/math/views/quatslice/QuatSlice.h | 329 +++ .../math/views/quatslice/QuatSliceData.h | 252 ++ .../mathtest/quatslice/DenseGeneralTest.h | 467 ++++ blazetest/src/mathtest/CMakeLists.txt | 1 + .../src/mathtest/quatslice/CMakeLists.txt | 43 + .../src/mathtest/quatslice/IncludeTest.cpp | 62 + 19 files changed, 5846 insertions(+), 13 deletions(-) create mode 100644 blaze_tensor/math/QuatSlice.h create mode 100644 blaze_tensor/math/constraints/QuatSlice.h create mode 100644 blaze_tensor/math/constraints/QuatSliceTensor.h create mode 100644 blaze_tensor/math/traits/QuatSliceTrait.h create mode 100644 blaze_tensor/math/typetraits/IsQuatSlice.h create mode 100644 blaze_tensor/math/typetraits/IsQuatSliceTensor.h create mode 100644 blaze_tensor/math/views/QuatSlice.h create mode 100644 blaze_tensor/math/views/quatslice/BaseTemplate.h create mode 100644 blaze_tensor/math/views/quatslice/Dense.h create mode 100644 blaze_tensor/math/views/quatslice/QuatSlice.h create mode 100644 blaze_tensor/math/views/quatslice/QuatSliceData.h create mode 100644 blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h create mode 100644 blazetest/src/mathtest/quatslice/CMakeLists.txt create mode 100644 blazetest/src/mathtest/quatslice/IncludeTest.cpp diff --git a/blaze_tensor/math/Constraints.h b/blaze_tensor/math/Constraints.h index ec622eb..8bd0b8f 100644 --- a/blaze_tensor/math/Constraints.h +++ b/blaze_tensor/math/Constraints.h @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include diff --git a/blaze_tensor/math/QuatSlice.h b/blaze_tensor/math/QuatSlice.h new file mode 100644 index 0000000..7e59f07 --- /dev/null +++ b/blaze_tensor/math/QuatSlice.h @@ -0,0 +1,156 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/QuatSlice.h +// \brief Header file for the complete QuatSlice implementation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_QUATSLICE_H_ +#define _BLAZE_TENSOR_MATH_QUATSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// RAND SPECIALIZATION FOR DENSE QUATSLICES +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the Rand class template for dense quatslices. +// \ingroup random +// +// This specialization of the Rand class randomizes dense quatslices. +*/ +template< typename MT // Type of the matrix + , size_t... CRAs > // Compile time quatslice arguments +class Rand< QuatSlice > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + template< typename RT > + inline void randomize( RT&& quatslice ) const; + + template< typename RT, typename Arg > + inline void randomize( RT&& quatslice, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a dense quatslice. +// +// \param quatslice The quatslice to be randomized. +// \return void +*/ +template< typename MT // Type of the matrix + , size_t... CRAs > // Compile time quatslice arguments +template< typename RT > // Type of the quatslice +inline void Rand< QuatSlice >::randomize( RT&& quatslice ) const +{ + using blaze::randomize; + + using QuatSliceType = RemoveReference_t; + + BLAZE_CONSTRAINT_MUST_BE_QUATSLICE_TYPE ( QuatSliceType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_TENSOR_TYPE( QuatSliceType ); + + for (size_t k = 0UL; k < quatslice.pages(); ++k) { + for (size_t i = 0UL; i < quatslice.rows(); ++i) { + for (size_t j = 0UL; j < quatslice.columns(); ++j) { + randomize(quatslice(k, i, j)); + } + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Randomization of a dense quatslice. +// +// \param quatslice The quatslice to be randomized. +// \param min The smallest possible value for a quatslice element. +// \param max The largest possible value for a quatslice element. +// \return void +*/ +template< typename MT // Type of the matrix + , size_t... CRAs > // Compile time quatslice arguments +template< typename RT // Type of the quatslice + , typename Arg > // Min/max argument type +inline void Rand< QuatSlice >::randomize( RT&& quatslice, const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + using QuatSliceType = RemoveReference_t; + + BLAZE_CONSTRAINT_MUST_BE_QUATSLICE_TYPE ( QuatSliceType ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_TENSOR_TYPE( QuatSliceType ); + + for (size_t k = 0UL; k < quatslice.pages(); ++k) { + for (size_t i = 0UL; i < quatslice.rows(); ++i) { + for (size_t j = 0UL; j < quatslice.columns(); ++j) { + randomize(quatslice(k, i, j), min, max); + } + } + } +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/Views.h b/blaze_tensor/math/Views.h index eb9663d..a7ea0fa 100644 --- a/blaze_tensor/math/Views.h +++ b/blaze_tensor/math/Views.h @@ -48,6 +48,7 @@ // #include #include #include +#include #include // #include #include diff --git a/blaze_tensor/math/constraints/QuatSlice.h b/blaze_tensor/math/constraints/QuatSlice.h new file mode 100644 index 0000000..7c2a605 --- /dev/null +++ b/blaze_tensor/math/constraints/QuatSlice.h @@ -0,0 +1,89 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/constraints/QuatSlice.h +// \brief Constraint on the data type +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_CONSTRAINTS_QUATSLICE_H_ +#define _BLAZE_TENSOR_MATH_CONSTRAINTS_QUATSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// MUST_BE_QUATSLICE_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is not a quatslice type (i.e. a dense or sparse quatslice), a compilation +// error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_QUATSLICE_TYPE(T) \ + static_assert( ::blaze::IsQuatSlice_v, "Non-quatslice type detected" ) +//************************************************************************************************* + + + + +//================================================================================================= +// +// MUST_NOT_BE_QUATSLICE_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is a quatslice type (i.e. a dense or sparse quatslice), a compilation +// error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_QUATSLICE_TYPE(T) \ + static_assert( !::blaze::IsQuatSlice_v, "QuatSlice type detected" ) +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/constraints/QuatSliceTensor.h b/blaze_tensor/math/constraints/QuatSliceTensor.h new file mode 100644 index 0000000..f50e57a --- /dev/null +++ b/blaze_tensor/math/constraints/QuatSliceTensor.h @@ -0,0 +1,89 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/constraints/QuatSliceTensor.h +// \brief Constraint on the transpose flag of tensor types +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_CONSTRAINTS_QUATSLICETENSOR_H_ +#define _BLAZE_TENSOR_MATH_CONSTRAINTS_QUATSLICETENSOR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + +namespace blaze { + +//================================================================================================= +// +// MUST_BE_QUATSLICE_TENSOR_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is not a row dense or sparse tensor type (i.e. a tensor type +// whose transposition flag is set to blaze::rowMajor) a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_QUATSLICE_TENSOR_TYPE(T) \ + static_assert( ::blaze::IsQuatSliceTensor_v, "Non-row-major tensor type detected" ) +//************************************************************************************************* + + + + +//================================================================================================= +// +// MUST_NOT_BE_QUATSLICE_TENSOR_TYPE CONSTRAINT +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constraint on the data type. +// \ingroup math_constraints +// +// In case the given data type \a T is a row dense or sparse tensor type (i.e. a tensor type +// whose transposition flag is set to blaze::rowMajor) a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_QUATSLICE_TENSOR_TYPE(T) \ + static_assert( !::blaze::IsQuatSliceTensor_v, "QuatSlice tensor type detected" ) +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/dense/DynamicTensor.h b/blaze_tensor/math/dense/DynamicTensor.h index 9b49655..4fc37f7 100644 --- a/blaze_tensor/math/dense/DynamicTensor.h +++ b/blaze_tensor/math/dense/DynamicTensor.h @@ -54,9 +54,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -3464,10 +3466,10 @@ template struct ColumnSliceTraitEval2< MT, M, EnableIf_t< IsDenseTensor_v && !IsUniform_v && - ( M == 0UL || Size_v< MT,0UL > == DefaultSize_v || - Size_v< MT,1UL > == DefaultSize_v ) && - ( M == 0UL || MaxSize_v< MT,0UL > == DefaultMaxSize_v || - MaxSize_v< MT,1UL > == DefaultMaxSize_v ) > > + ( Size_v< MT,0UL > == DefaultSize_v || + Size_v< MT,1UL > == DefaultSize_v ) && + ( MaxSize_v< MT,0UL > == DefaultMaxSize_v || + MaxSize_v< MT,1UL > == DefaultMaxSize_v ) > > { using Type = DynamicMatrix< RemoveConst_t< ElementType_t >, rowMajor >; }; @@ -3489,10 +3491,10 @@ template struct PageSliceTraitEval2< MT, M, EnableIf_t< IsDenseTensor_v && !IsUniform_v && - ( M == 0UL || Size_v< MT,1UL > == DefaultSize_v || - Size_v< MT,2UL > == DefaultSize_v ) && - ( M == 0UL || MaxSize_v< MT,1UL > == DefaultMaxSize_v || - MaxSize_v< MT,2UL > == DefaultMaxSize_v ) > > + ( Size_v< MT,1UL > == DefaultSize_v || + Size_v< MT,2UL > == DefaultSize_v ) && + ( MaxSize_v< MT,1UL > == DefaultMaxSize_v || + MaxSize_v< MT,2UL > == DefaultMaxSize_v ) > > { using Type = DynamicMatrix< RemoveConst_t< ElementType_t >, rowMajor >; }; @@ -3501,6 +3503,31 @@ struct PageSliceTraitEval2< +//================================================================================================= +// +// QUATSLICETRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template +struct QuatSliceTraitEval2< + MT, M, + EnableIf_t< IsDenseArray_v && + ( Size_v< MT,1UL > == DefaultSize_v || + Size_v< MT,2UL > == DefaultSize_v || + Size_v< MT,3UL > == DefaultSize_v ) && + ( MaxSize_v< MT,1UL > == DefaultMaxSize_v || + MaxSize_v< MT,2UL > == DefaultMaxSize_v || + MaxSize_v< MT,3UL > == DefaultMaxSize_v ) > > +{ + using Type = DynamicTensor< RemoveConst_t< ElementType_t > >; +}; +/*! \endcond */ +//************************************************************************************************* + + //================================================================================================= // @@ -3514,10 +3541,10 @@ template struct RowSliceTraitEval2< MT, M, EnableIf_t< IsDenseTensor_v && !IsUniform_v && - ( M == 0UL || Size_v< MT,0UL > == DefaultSize_v || - Size_v< MT,2UL > == DefaultSize_v ) && - ( M == 0UL || MaxSize_v< MT,0UL > == DefaultMaxSize_v || - MaxSize_v< MT,2UL > == DefaultMaxSize_v ) > > + ( Size_v< MT,0UL > == DefaultSize_v || + Size_v< MT,2UL > == DefaultSize_v ) && + ( MaxSize_v< MT,0UL > == DefaultMaxSize_v || + MaxSize_v< MT,2UL > == DefaultMaxSize_v ) > > { using Type = DynamicMatrix< RemoveConst_t< ElementType_t >, columnMajor >; }; diff --git a/blaze_tensor/math/smp/DenseArray.h b/blaze_tensor/math/smp/DenseArray.h index b846b92..b6bca62 100644 --- a/blaze_tensor/math/smp/DenseArray.h +++ b/blaze_tensor/math/smp/DenseArray.h @@ -47,7 +47,7 @@ #if BLAZE_HPX_PARALLEL_MODE #include #elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE -#include +//#include #elif BLAZE_OPENMP_PARALLEL_MODE #include #else diff --git a/blaze_tensor/math/traits/QuatSliceTrait.h b/blaze_tensor/math/traits/QuatSliceTrait.h new file mode 100644 index 0000000..2cdb2f3 --- /dev/null +++ b/blaze_tensor/math/traits/QuatSliceTrait.h @@ -0,0 +1,208 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/traits/QuatSliceTrait.h +// \brief Header file for the quat trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TRAITS_QUATSLICETRAIT_H_ +#define _BLAZE_TENSOR_MATH_TRAITS_QUATSLICETRAIT_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename, size_t... > struct QuatSliceTrait; +template< typename, size_t, typename = void > struct QuatSliceTraitEval1; +template< typename, size_t, typename = void > struct QuatSliceTraitEval2; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< size_t I, typename T > +auto evalQuatSliceTrait( T& ) + -> typename QuatSliceTraitEval1::Type; + +template< typename T > +auto evalQuatSliceTrait( T& ) + -> typename QuatSliceTraitEval2::Type; + +template< size_t I, typename T > +auto evalQuatSliceTrait( const T& ) + -> typename QuatSliceTrait::Type; + +template< typename T > +auto evalQuatSliceTrait( const T& ) + -> typename QuatSliceTrait::Type; + +template< size_t I, typename T > +auto evalQuatSliceTrait( const volatile T& ) + -> typename QuatSliceTrait::Type; + +template< typename T > +auto evalQuatSliceTrait( const volatile T& ) + -> typename QuatSliceTrait::Type; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Base template for the QuatSliceTrait class. +// \ingroup math_traits +// +// \section quattrait_general General +// +// The QuatSliceTrait class template offers the possibility to select the resulting data type when +// creating a view on a specific quat of a dense or sparse tensor. QuatSliceTrait defines the nested +// type \a Type, which represents the resulting data type of the quat operation. In case the +// given data type is not a dense or sparse tensor type, the resulting data type \a Type is +// set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference modifiers +// are generally ignored. +// +// +// \section quattrait_specializations Creating custom specializations +// +// Per default, QuatSliceTrait supports all tensor types of the Blaze library (including views and +// adaptors). For all other data types it is possible to specialize the QuatSliceTrait template. The +// following example shows the according specialization for the DynamicTensor class template: + + \code + template< typename T1, size_t... CRAs > + struct QuatSliceTrait< DynamicTensor, CRAs... > + { + using Type = DynamicMatrix; + }; + \endcode + +// \n \section quatslicetrait_examples Examples +// +// The following example demonstrates the use of the QuatSliceTrait template, where depending on +// the given tensor type the resulting quat type is selected: + + \code + // Definition of the quat type of a dynamic tensor + using TensorType1 = blaze::DynamicTensor; + using ResultType1 = typename blaze::QuatSliceTrait::Type; + \endcode +*/ +template< typename MT // Type of the tensor + , size_t... CRAs > // Compile time quat arguments +struct QuatSliceTrait +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = decltype( evalQuatSliceTrait( std::declval() ) ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary alias declaration for the QuatSliceTrait type trait. +// \ingroup math_traits +// +// The QuatSliceTrait_t alias declaration provides a convenient shortcut to access the nested +// \a Type of the QuatSliceTrait class template. For instance, given the tensor type \a MT the +// following two type definitions are identical: + + \code + using Type1 = typename blaze::QuatSliceTrait::Type; + using Type2 = blaze::QuatSliceTrait_t; + \endcode +*/ +template< typename MT // Type of the tensor + , size_t... CRAs > // Compile time quat arguments +using QuatSliceTrait_t = typename QuatSliceTrait::Type; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief First auxiliary helper struct for the QuatSliceTrait type trait. +// \ingroup math_traits +*/ +template< typename MT // Type of the tensor + , size_t I // Compile time quat index + , typename > // Restricting condition +struct QuatSliceTraitEval1 +{ + public: + //********************************************************************************************** + using Type = typename QuatSliceTraitEval2::Type; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Second auxiliary helper struct for the QuatSliceTrait type trait. +// \ingroup math_traits +*/ +template< typename MT // Type of the tensor + , size_t I // Compile time quat index + , typename > // Restricting condition +struct QuatSliceTraitEval2 +{ + public: + //********************************************************************************************** + using Type = INVALID_TYPE; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsQuatSlice.h b/blaze_tensor/math/typetraits/IsQuatSlice.h new file mode 100644 index 0000000..9a89afb --- /dev/null +++ b/blaze_tensor/math/typetraits/IsQuatSlice.h @@ -0,0 +1,169 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/typetraits/IsQuatSlice.h +// \brief Header file for the IsQuatSlice type trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISQUATSLICE_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISQUATSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Compile time check for quatslices. +// \ingroup math_type_traits +// +// This type trait tests whether or not the given template parameter is a quatslice (i.e. a view on a +// quatslice of a dense or sparse matrix). In case the type is a quatslice, the \a value member constant is +// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from +// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class +// derives from \a FalseType. + + \code + using blaze::aligned; + + using MatrixType1 = blaze::StaticMatrix; + using MatrixType2 = blaze::DynamicMatrix; + using MatrixType3 = blaze::CompressedMatrix; + + MatrixType1 A; + MatrixType2 B( 100UL, 200UL ); + MatrixType3 C( 200UL, 250UL ); + + using QuatSliceType1 = decltype( blaze::quatslice<4UL>( A ) ); + using QuatSliceType2 = decltype( blaze::quatslice( B, 16UL ) ); + using QuatSliceType3 = decltype( blaze::quatslice( C, 17UL ) ); + + blaze::IsQuatSlice< QuatSliceType1 >::value // Evaluates to 1 + blaze::IsQuatSlice< const QuatSliceType2 >::Type // Results in TrueType + blaze::IsQuatSlice< volatile QuatSliceType3 > // Is derived from TrueType + blaze::IsQuatSlice< MatrixType1 >::value // Evaluates to 0 + blaze::IsQuatSlice< const MatrixType2 >::Type // Results in FalseType + blaze::IsQuatSlice< volatile MatrixType3 > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsQuatSlice + : public FalseType +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsQuatSlice type trait for 'QuatSlice'. +// \ingroup math_type_traits +*/ +template< typename MT, size_t... CRAs > +struct IsQuatSlice< QuatSlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsQuatSlice type trait for 'const QuatSlice'. +// \ingroup math_type_traits +*/ +template< typename MT, size_t... CRAs > +struct IsQuatSlice< const QuatSlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsQuatSlice type trait for 'volatile QuatSlice'. +// \ingroup math_type_traits +*/ +template< typename MT, size_t... CRAs > +struct IsQuatSlice< volatile QuatSlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsQuatSlice type trait for 'const volatile QuatSlice'. +// \ingroup math_type_traits +*/ +template< typename MT, size_t... CRAs > +struct IsQuatSlice< const volatile QuatSlice > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary variable template for the IsQuatSlice type trait. +// \ingroup type_traits +// +// The IsQuatSlice_v variable template provides a convenient shortcut to access the nested \a value +// of the IsQuatSlice class template. For instance, given the type \a T the following two statements +// are identical: + + \code + constexpr bool value1 = blaze::IsQuatSlice::value; + constexpr bool value2 = blaze::IsQuatSlice_v; + \endcode +*/ +template< typename T > +constexpr bool IsQuatSlice_v = IsQuatSlice::value; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsQuatSliceTensor.h b/blaze_tensor/math/typetraits/IsQuatSliceTensor.h new file mode 100644 index 0000000..1f903a6 --- /dev/null +++ b/blaze_tensor/math/typetraits/IsQuatSliceTensor.h @@ -0,0 +1,135 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/typetraits/IsQuatSliceTensor.h +// \brief Header file for the IsQuatSliceTensor type trait +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISQUATSLICETENSOR_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISQUATSLICETENSOR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the IsQuatSliceTensor type trait. +// \ingroup math_type_traits +*/ +template< typename T > +struct IsQuatSliceTensorHelper +{ + private: + //********************************************************************************************** + template< typename TT > + static TrueType test( const Tensor& ); + + template< typename TT > + static TrueType test( const volatile Tensor& ); + + static FalseType test( ... ); + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = decltype( test( std::declval() ) ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time check for quatslice tensor types. +// \ingroup math_type_traits +// +// This type trait tests whether or not the given template argument is a quatslice dense or sparse +// tensor type (i.e. a tensor whose transposition flag is set to blaze::rowMajor). In case +// the type is a quatslice tensor type, the \a value member constant is set to \a true, the nested +// type definition \a Type is \a TrueType, and the class derives from \a TrueType. Otherwise +// \a value is set to \a false, \a Type is \a FalseType, and the class derives from \a FalseType. + + \code + using blaze::rowMajor; + using blaze::columnTensor; + + blaze::IsQuatSliceTensor< StaticTensor >::value // Evaluates to 1 + blaze::IsQuatSliceTensor< const DynamicTensor >::Type // Results in TrueType + blaze::IsQuatSliceTensor< volatile CompressedTensor > // Is derived from TrueType + blaze::IsQuatSliceTensor< StaticTensor >::value // Evaluates to 0 + blaze::IsQuatSliceTensor< const DynamicTensor >::Type // Results in FalseType + blaze::IsQuatSliceTensor< volatile CompressedTensor > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsQuatSliceTensor + : public IsQuatSliceTensorHelper::Type +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Auxiliary variable template for the IsQuatSliceTensor type trait. +// \ingroup type_traits +// +// The IsQuatSliceTensor_v variable template provides a convenient shortcut to access the nested +// \a value of the IsQuatSliceTensor class template. For instance, given the type \a T the following +// two statements are identical: + + \code + constexpr bool value1 = blaze::IsQuatSliceTensor::value; + constexpr bool value2 = blaze::IsQuatSliceTensor_v; + \endcode +*/ +template< typename T > +constexpr bool IsQuatSliceTensor_v = IsQuatSliceTensor::value; +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/QuatSlice.h b/blaze_tensor/math/views/QuatSlice.h new file mode 100644 index 0000000..f863d6f --- /dev/null +++ b/blaze_tensor/math/views/QuatSlice.h @@ -0,0 +1,1631 @@ +//================================================================================================= +/*! +// \file blaze_quaternion/math/views/QuatSlice.h +// \brief Header file for the implementation of the QuatSlice view +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + +#include +//#include +//#include +#include +#include +#include +#include +//#include +//#include +#include +//#include +//#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Creating a view on a specific quatslice of the given quaternion. +// \ingroup quatslice +// +// \param quaternion The quaternion containing the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the quaternion. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given quaternion. + + \code + blaze::DynamicArray D; + blaze::CompressedArray S; + // ... Resizing and initialization + + // Creating a view on the 3rd quatslice of the dense quaternion D + auto quatslice3 = quatslice<3UL>( D ); + + // Creating a view on the 4th quatslice of the sparse quaternion S + auto quatslice4 = quatslice<4UL>( S ); + \quat() + +// By default, the provided quatslice arguments are checked at runtime. In case the quatslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the quatslices +// in the given quaternion) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto quatslice3 = quatslice<3UL>( D, unchecked ); + auto quatslice4 = quatslice<4UL>( S, unchecked ); + \quat() +*/ +template< size_t I // QuatSlice index + , typename AT // Type of the quaternion + , typename... RRAs > // Optional quatslice arguments +inline decltype(auto) quatslice( Array& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = QuatSlice_; + return ReturnType( ~quaternion, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific quatslice of the given constant quaternion. +// \ingroup quatslice +// +// \param quaternion The constant quaternion containing the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the quaternion. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given constant +// quaternion. + + \code + + const blaze::DynamicArray D( ... ); + const blaze::CompressedArray S( ... ); + + // Creating a view on the 3rd quatslice of the dense quaternion D + auto quatslice3 = quatslice<3UL>( D ); + + // Creating a view on the 4th quatslice of the sparse quaternion S + auto quatslice4 = quatslice<4UL>( S ); + \quat() + +// By default, the provided quatslice arguments are checked at runtime. In case the quatslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the quatslices +// in the given quaternion) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto quatslice3 = quatslice<3UL>( D, unchecked ); + auto quatslice4 = quatslice<4UL>( S, unchecked ); + \quat() +*/ +template< size_t I // QuatSlice index + , typename AT // Type of the quaternion + , typename... RRAs > // Optional quatslice arguments +inline decltype(auto) quatslice( const Array& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const QuatSlice_; + return ReturnType( ~quaternion, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific quatslice of the given temporary quaternion. +// \ingroup quatslice +// +// \param quaternion The temporary quaternion containing the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the quaternion. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given temporary +// quaternion. In case the quatslice is not properly specified (i.e. if the specified index is greater +// than or equal to the total number of the quatslices in the given quaternion) a \a std::invalid_argument +// exception is thrown. +*/ +template< size_t I // QuatSlice index + , typename AT // Type of the quaternion + , typename... RRAs > // Optional quatslice arguments +inline decltype(auto) quatslice( Array&& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = QuatSlice_; + return ReturnType( ~quaternion, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific quatslice of the given quaternion. +// \ingroup quatslice +// +// \param quaternion The quaternion containing the quatslice. +// \param index The index of the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the quaternion. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given quaternion. + + \code + blaze::DynamicArray D; + blaze::CompressedArray S; + // ... Resizing and initialization + + // Creating a view on the 3rd quatslice of the dense quaternion D + auto quatslice3 = quatslice( D, 3UL ); + + // Creating a view on the 4th quatslice of the sparse quaternion S + auto quatslice4 = quatslice( S, 4UL ); + \quat() + +// By default, the provided quatslice arguments are checked at runtime. In case the quatslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the quatslices +// in the given quaternion) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto quatslice3 = quatslice( D, 3UL, unchecked ); + auto quatslice4 = quatslice( S, 4UL, unchecked ); + \quat() +*/ +template< typename AT // Type of the quaternion + , typename... RRAs > // Optional quatslice arguments +inline decltype(auto) quatslice( Array& quaternion, size_t index, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = QuatSlice_; + return ReturnType( ~quaternion, index, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific quatslice of the given constant quaternion. +// \ingroup quatslice +// +// \param quaternion The constant quaternion containing the quatslice. +// \param index The index of the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the quaternion. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given constant +// quaternion. + + \code + const blaze::DynamicArray D( ... ); + const blaze::CompressedArray S( ... ); + + // Creating a view on the 3rd quatslice of the dense quaternion D + auto quatslice3 = quatslice( D, 3UL ); + + // Creating a view on the 4th quatslice of the sparse quaternion S + auto quatslice4 = quatslice( S, 4UL ); + \quat() + +// By default, the provided quatslice arguments are checked at runtime. In case the quatslice is not properly +// specified (i.e. if the specified index is greater than or equal to the total number of the quatslices +// in the given quaternion) a \a std::invalid_argument exception is thrown. The checks can be skipped +// by providing the optional \a blaze::unchecked argument. + + \code + auto quatslice3 = quatslice( D, 3UL, unchecked ); + auto quatslice4 = quatslice( S, 4UL, unchecked ); + \quat() +*/ +template< typename AT // Type of the quaternion + , typename... RRAs > // Optional quatslice arguments +inline decltype(auto) quatslice( const Array& quaternion, size_t index, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = const QuatSlice_; + return ReturnType( ~quaternion, index, args... ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Creating a view on a specific quatslice of the given temporary quaternion. +// \ingroup quatslice +// +// \param quaternion The temporary quaternion containing the quatslice. +// \param index The index of the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the quaternion. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given temporary +// quaternion. In case the quatslice is not properly specified (i.e. if the specified index is greater +// than or equal to the total number of the quatslices in the given quaternion) a \a std::invalid_argument +// exception is thrown. +*/ +template< typename AT // Type of the quaternion + , typename... RRAs > // Optional quatslice arguments +inline decltype(auto) quatslice( Array&& quaternion, size_t index, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + using ReturnType = QuatSlice_; + return ReturnType( ~quaternion, index, args... ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion/quaternion addition. +// \ingroup quatslice +// +// \param quaternion The constant quaternion/quaternion addition. +// \param args The runtime quatslice arguments. +// \return View on the specified quatslice of the addition. +// +// This function returns an expression representing the specified quatslice of the given quaternion/quaternion +// addition. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const ArrArrAddExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( (~quaternion).leftOperand(), args... ) + +// quatslice( (~quaternion).rightOperand(), args... ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion/quaternion subtraction. +// \ingroup quatslice +// +// \param quaternion The constant quaternion/quaternion subtraction. +// \param args The runtime quatslice arguments. +// \return View on the specified quatslice of the subtraction. +// +// This function returns an expression representing the specified quatslice of the given quaternion/quaternion +// subtraction. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const ArrArrSubExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( (~quaternion).leftOperand(), args... ) - +// quatslice( (~quaternion).rightOperand(), args... ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given Schur product. +// \ingroup quatslice +// +// \param quaternion The constant Schur product. +// \param args The runtime quatslice arguments. +// \return View on the specified quatslice of the Schur product. +// +// This function returns an expression representing the specified quatslice of the given Schur product. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const SchurExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( (~quaternion).leftOperand(), args... ) * +// quatslice( (~quaternion).rightOperand(), args... ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion/quaternion multiplication. +// \ingroup quatslice +// +// \param quaternion The constant quaternion/quaternion multiplication. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the multiplication. +// +// This function returns an expression representing the specified quatslice of the given quaternion/quaternion +// multiplication. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const ArrArrMultExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( (~quaternion).leftOperand(), args... ) * (~quaternion).rightOperand(); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given outer product. +// \ingroup quatslice +// +// \param quaternion The constant outer product. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the outer product. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given outer product. +*/ +// template< size_t I // QuatSlice index +// , typename AT // Array base type of the expression +// , typename... RRAs > // Optional quatslice arguments +// inline decltype(auto) quatslice( const VecTVecMultExpr& quaternion, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// MAYBE_UNUSED( args... ); +// +// if( !Contains_v< TypeList, Unchecked > ) { +// if( (~quaternion).quatslices() <= I ) { +// BLAZE_THQUATSLICE_INVALID_ARGUMENT( "Invalid quatslice access index" ); +// } +// } +// +// return (~quaternion).leftOperand()[I] * (~quaternion).rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given outer product. +// \ingroup quatslice +// +// \param quaternion The constant outer product. +// \param index The index of the quatslice. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the outer product. +// \exception std::invalid_argument Invalid quatslice access index. +// +// This function returns an expression representing the specified quatslice of the given outer product. +*/ +// template< typename AT // Array base type of the expression +// , typename... RRAs > // Optional quatslice arguments +// inline decltype(auto) quatslice( const VecTVecMultExpr& quaternion, size_t index, RRAs... args ) +// { +// BLAZE_FUNCTION_TRACE; +// +// MAYBE_UNUSED( args... ); +// +// if( !Contains_v< TypeList, Unchecked > ) { +// if( (~quaternion).quatslices() <= index ) { +// BLAZE_THQUATSLICE_INVALID_ARGUMENT( "Invalid quatslice access index" ); +// } +// } +// +// return (~quaternion).leftOperand()[index] * (~quaternion).rightOperand(); +// } +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion/scalar multiplication. +// \ingroup quatslice +// +// \param quaternion The constant quaternion/scalar multiplication. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the multiplication. +// +// This function returns an expression representing the specified quatslice of the given quaternion/scalar +// multiplication. +*/ +template< size_t... CRAs // Compile time quatslice arguments + , typename AT // Array base type of the expression + , typename... RRAs > // Runtime quatslice arguments +inline decltype(auto) quatslice( const ArrScalarMultExpr& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return quatslice( (~quaternion).leftOperand(), args... ) * (~quaternion).rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion/scalar division. +// \ingroup quatslice +// +// \param quaternion The constant quaternion/scalar division. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the division. +// +// This function returns an expression representing the specified quatslice of the given quaternion/scalar +// division. +*/ +template< size_t... CRAs // Compile time quatslice arguments + , typename AT // Array base type of the expression + , typename... RRAs > // Runtime quatslice arguments +inline decltype(auto) quatslice( const ArrScalarDivExpr& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return quatslice( (~quaternion).leftOperand(), args... ) / (~quaternion).rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given unary quaternion map operation. +// \ingroup quatslice +// +// \param quaternion The constant unary quaternion map operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the unary map operation. +// +// This function returns an expression representing the specified quatslice of the given unary quaternion +// map operation. +*/ +template< size_t... CRAs // Compile time quatslice arguments + , typename AT // Array base type of the expression + , typename... RRAs > // Runtime quatslice arguments +inline decltype(auto) quatslice( const ArrMapExpr& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return map( quatslice( (~quaternion).operand(), args... ), (~quaternion).operation() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given binary quaternion map operation. +// \ingroup quatslice +// +// \param quaternion The constant binary quaternion map operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the binary map operation. +// +// This function returns an expression representing the specified quatslice of the given binary quaternion +// map operation. +*/ +template< size_t... CRAs // Compile time quatslice arguments + , typename AT // Array base type of the expression + , typename... RRAs > // Runtime quatslice arguments +inline decltype(auto) quatslice( const ArrArrMapExpr& quaternion, RRAs... args ) +{ + BLAZE_FUNCTION_TRACE; + + return map( quatslice( (~quaternion).leftOperand(), args... ), + quatslice( (~quaternion).rightOperand(), args... ), + (~quaternion).operation() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion evaluation operation. +// \ingroup quatslice +// +// \param quaternion The constant quaternion evaluation operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the evaluation operation. +// +// This function returns an expression representing the specified quatslice of the given quaternion +// evaluation operation. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const ArrEvalExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return eval( quatslice( (~quaternion).operand(), args... ) ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion serialization operation. +// \ingroup quatslice +// +// \param quaternion The constant quaternion serialization operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the serialization operation. +// +// This function returns an expression representing the specified quatslice of the given quaternion +// serialization operation. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const ArrSerialExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return serial( quatslice( (~quaternion).operand(), args... ) ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion declaration operation. +// \ingroup quatslice +// +// \param quaternion The constant quaternion declaration operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the declaration operation. +// +// This function returns an expression representing the specified quatslice of the given quaternion +// declaration operation. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const DeclExpr& quaternion, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( (~quaternion).operand(), args... ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion transpose operation. +// \ingroup quatslice +// +// \param quaternion The constant quaternion transpose operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the transpose operation. +// +// This function returns an expression representing the specified quatslice of the given quaternion +// transpose operation. +*/ +//template< size_t MK // Compile time quatslice arguments +// , size_t MI +// , size_t MJ +// , typename AT // Array base type of the expression +// , typename... RRAs > // Runtime arguments +//inline decltype(auto) quatslice( const ArrTransExpr& quaternion, size_t index, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( evaluate( ~quaternion ), index, args... ); +//} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given quaternion transpose operation. +// \ingroup quatslice +// +// \param quaternion The constant quaternion transpose operation. +// \param args The runtime quatslice arguments +// \return View on the specified quatslice of the transpose operation. +// +// This function returns an expression representing the specified quatslice of the given quaternion +// transpose operation. +*/ +//template< typename AT // Array base type of the expression +// , typename... RRAs > // Runtime arguments +//inline decltype(auto) quatslice( const ArrTransExpr& quaternion, size_t index, RRAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return quatslice( evaluate( ~quaternion ), index, args... ); +//} +/*! \endcond */ +//************************************************************************************************* + + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a specific quatslice of the given matrix expansion operation. +// \ingroup subquaternion +// +// \param quaternion The constant matrix expansion operation. +// \param args Optional quatslice arguments. +// \return View on the specified quatslice of the expansion operation. +// +// This function returns an expression representing the specified quatslice of the given matrix +// expansion operation. +*/ +//template< size_t... CRAs // Compile time quatslice arguments +// , typename AT // Matrix base type of the expression +// , size_t... CEAs // Compile time expansion arguments +// , typename... RSAs > // Runtime quatslice arguments +//inline decltype(auto) quatslice( const TensExpandExpr& quaternion, RSAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// MAYBE_UNUSED( args... ); +// +// return submatrix( (~quaternion).operand(), 0UL, 0UL, (~quaternion).rows(), (~quaternion).columns() ); +//} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL RESTRUCTURING FUNCTIONS (ROW) +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Creating a view on a selection of row of the given quaternion/vector multiplication. +// \ingroup quatslice +// +// \param matrix The constant quaternion/vector multiplication. +// \param args The runtime element arguments. +// \return View on the specified row of the multiplication. +// +// This function returns an expression representing the specified elements of the given +// matrix/vector multiplication. +*/ +//template< size_t... CEAs // Compile time element arguments +// , typename AT // Matrix base type of the expression +// , typename... REAs > // Runtime element arguments +//inline decltype(auto) row( const ArrVecMultExpr& matrix, REAs... args ) +//{ +// BLAZE_FUNCTION_TRACE; +// +// return trans(quatslice( (~matrix).leftOperand(), args... ) * (~matrix).rightOperand()); +//} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// QUATSLICE OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Resetting the given quatslice. +// \ingroup quatslice +// +// \param quatslice The quatslice to be resetted. +// \return void +*/ +template< typename AT // Type of the quaternion + // Density flag + // Symmetry flag + , size_t... CRAs > // Compile time quatslice arguments +inline void reset( QuatSlice& quatslice ) +{ + quatslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Resetting the given temporary quatslice. +// \ingroup quatslice +// +// \param quatslice The temporary quatslice to be resetted. +// \return void +*/ +template< typename AT // Type of the quaternion + // Density flag + // Symmetry flag + , size_t... CRAs > // Compile time quatslice arguments +inline void reset( QuatSlice&& quatslice ) +{ + quatslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Clearing the given quatslice. +// \ingroup quatslice +// +// \param quatslice The quatslice to be cleared. +// \return void +// +// Clearing a quatslice is equivalent to resetting it via the reset() function. +*/ +template< typename AT // Type of the quaternion + // Density flag + // Symmetry flag + , size_t... CRAs > // Compile time quatslice arguments +inline void clear( QuatSlice& quatslice ) +{ + quatslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Clearing the given temporary quatslice. +// \ingroup quatslice +// +// \param quatslice The temporary quatslice to be cleared. +// \return void +// +// Clearing a quatslice is equivalent to resetting it via the reset() function. +*/ +template< typename AT // Type of the quaternion + // Density flag + // Symmetry flag + , size_t... CRAs > // Compile time quatslice arguments +inline void clear( QuatSlice&& quatslice ) +{ + quatslice.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the given dense quatslice is in default state. +// \ingroup quatslice +// +// \param quatslice The dense quatslice to be tested for its default state. +// \return \a true in case the given dense quatslice is component-wise zero, \a false otherwise. +// +// This function checks whether the dense quatslice is in default state. For instance, in case the +// quatslice is instantiated for a built-in integral or floating point data type, the function returns +// \a true in case all quatslice elements are 0 and \a false in case any quatslice element is not 0. The +// following example demonstrates the use of the \a isDefault function: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + if( isDefault( quatslice( A, 0UL ) ) ) { ... } + \quat() + +// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed +// semantics (blaze::relaxed): + + \code + if( isDefault( quatslice( A, 0UL ) ) ) { ... } + \quat() +*/ +template< bool RF // Relaxation flag + , typename AT // Type of the quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline bool isDefault( const QuatSlice& quatslice ) +{ + using blaze::isDefault; + + for( size_t k=0UL; k<(~sm).pages(); ++k ) + for( size_t i=0UL; i( quatslice(k, i, j) ) ) + return false; + return true; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the invariants of the given quatslice are intact. +// \ingroup quatslice +// +// \param quatslice The quatslice to be tested. +// \return \a true in case the given quatslice's invariants are intact, \a false otherwise. +// +// This function checks whether the invariants of the quatslice are intact, i.e. if its state is valid. +// In case the invariants are intact, the function returns \a true, else it will return \a false. +// The following example demonstrates the use of the \a isIntact() function: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + if( isIntact( quatslice( A, 0UL ) ) ) { ... } + \quat() +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline bool isIntact( const QuatSlice& quatslice ) noexcept +{ + return ( quatslice.quat() < quatslice.operand().quats() && + isIntact( quatslice.operand() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the two given quatslices represent the same observable state. +// \ingroup quatslice +// +// \param a The first quatslice to be tested for its state. +// \param b The second quatslice to be tested for its state. +// \return \a true in case the two quatslices share a state, \a false otherwise. +// +// This overload of the isSame() function tests if the two given quatslices refer to exactly the same +// range of the same quaternion. In case both quatslices represent the same observable state, the function +// returns \a true, otherwise it returns \a false. +*/ +template< typename AT1 // Type of the quaternion of the left-hand side quatslice + , size_t... CRAs1 // Compile time quatslice arguments of the left-hand side quatslice + , typename AT2 // Type of the quaternion of the right-hand side quatslice + , size_t... CRAs2 > // Compile time quatslice arguments of the right-hand side quatslice +inline bool isSame( const QuatSlice& a, + const QuatSlice& b ) noexcept +{ + return ( isSame( a.operand(), b.operand() ) && ( a.quat() == b.quat() ) ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by setting a single element of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param i The row to be set. +// \param j The column to be set. +// \param value The value to be set to the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +inline bool trySet( const QuatSlice& quatslice, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( k < quatslice.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( i < quatslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < quatslice.columns(), "Invalid column access index" ); + + return trySet( quatslice.operand(), quatslice.quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by adding to a single element of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param i The row to be modified. +// \param j The column to be modified. +// \param value The value to be added to the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +inline bool tryAdd( const QuatSlice& quatslice, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( k < quatslice.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( i < quatslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < quatslice.columns(), "Invalid column access index" ); + + return tryAdd( quatslice.operand(), quatslice.quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by subtracting from a single element of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param i The row to be modified. +// \param j The column to be modified. +// \param value The value to be subtracted from the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +inline bool trySub( const QuatSlice& quatslice, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( k < quatslice.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( i < quatslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < quatslice.columns(), "Invalid column access index" ); + + return trySub( quatslice.operand(), quatslice.quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a single element of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param i The row to be modified. +// \param j The column to be modified. +// \param value The factor for the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +inline bool tryMult( const QuatSlice& quatslice, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( k < quatslice.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( i < quatslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < quatslice.columns(), "Invalid column access index" ); + + return tryMult( quatslice.operand(), quatslice.quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a range of elements of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param index The index of the first element of the range to be modified. +// \param size The number of elements of the range to be modified. +// \param value The factor for the elements. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool + tryMult( const QuatSlice& quatslice, size_t page, size_t row, size_t col, size_t pages, size_t rows, size_t cols, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( page <= (~quatslice).pages(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( page + pages <= (~quatslice).pages(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( row <= (~quatslice).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( row + rows <= (~quatslice).rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( col <= (~quatslice).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( col + cols <= (~quatslice).columns(), "Invalid columns range size" ); + + return tryMult( quatslice.operand(), quatslice.quat(), page, row, col, 1UL, pages, rows, cols, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a single element of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param index The index of the element to be modified. +// \param value The divisor for the element. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +inline bool tryDiv( const QuatSlice& quatslice, size_t k, size_t i, size_t j, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( k < quatslice.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( i < quatslice.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( j < quatslice.columns(), "Invalid column access index" ); + + return tryDiv( quatslice.operand(), quatslice.quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by scaling a range of elements of a quatslice. +// \ingroup quatslice +// +// \param quatslice The target quatslice. +// \param index The index of the first element of the range to be modified. +// \param size The number of elements of the range to be modified. +// \param value The divisor for the elements. +// \return \a true in case the operation would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename ET > // Type of the element +BLAZE_ALWAYS_INLINE bool + tryDiv( const QuatSlice& quatslice, size_t page, size_t row, size_t col, size_t pages, size_t rows, size_t cols, const ET& value ) +{ + BLAZE_INTERNAL_ASSERT( page <= (~quatslice).pages(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( page + pages <= (~quatslice).pages(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( row <= (~quatslice).rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( row + rows <= (~quatslice).rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( col <= (~quatslice).columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( col + cols <= (~quatslice).columns(), "Invalid columns range size" ); + + return tryDiv( quatslice.operand(), quatslice.quat(), page, row, col, 1UL, pages, rows, cols, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the assignment of a matrix to a quatslice. +// \ingroup quatslice +// +// \param lhs The target left-hand side quatslice. +// \param rhs The right-hand side vector to be assigned. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename TT > // Type of the right-hand side tensor +inline bool tryAssign( const QuatSlice& lhs, + const Tensor& rhs, size_t k, size_t i, size_t j ) +{ + BLAZE_INTERNAL_ASSERT( k <= lhs.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( k + (~rhs).pages() <= lhs.pages(), "Invalid page range size" ); + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryAssign( lhs.operand(), ~rhs, lhs.quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the addition assignment of a vector to a quatslice. +// \ingroup quatslice +// +// \param lhs The target left-hand side quatslice. +// \param rhs The right-hand side vector to be added. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename TT > // Type of the right-hand side matrix +inline bool tryAddAssign( const QuatSlice& lhs, + const Tensor& rhs, size_t k, size_t i, size_t j ) +{ + BLAZE_INTERNAL_ASSERT( k <= lhs.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( k + (~rhs).pages() <= lhs.pages(), "Invalid page range size" ); + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryAddAssign( lhs.operand(), ~rhs, lhs.quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the subtraction assignment of a vector to a quatslice. +// \ingroup quatslice +// +// \param lhs The target left-hand side quatslice. +// \param rhs The right-hand side vector to be subtracted. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename TT > // Type of the right-hand side matrix +inline bool trySubAssign( const QuatSlice& lhs, + const Tensor& rhs, size_t k, size_t i, size_t j ) +{ + BLAZE_INTERNAL_ASSERT( k <= lhs.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( k + (~rhs).pages() <= lhs.pages(), "Invalid page range size" ); + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return trySubAssign( lhs.operand(), ~rhs, lhs.quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the multiplication assignment of a vector to a quatslice. +// \ingroup quatslice +// +// \param lhs The target left-hand side quatslice. +// \param rhs The right-hand side vector to be multiplied. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename VT > // Type of the right-hand side matrix +inline bool tryMultAssign( const QuatSlice& lhs, + const Vector& rhs, size_t k, size_t i, size_t j ) +{ + BLAZE_INTERNAL_ASSERT( k <= lhs.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( k + (~rhs).pages() <= lhs.pages(), "Invalid page range size" ); + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryMultAssign( lhs.operand(), ~rhs, lhs.quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Predict invariant violations by the division assignment of a vector to a quatslice. +// \ingroup quatslice +// +// \param lhs The target left-hand side quatslice. +// \param rhs The right-hand side vector divisor. +// \param index The index of the first element to be modified. +// \return \a true in case the assignment would be successful, \a false if not. +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CRAs // Compile time quatslice arguments + , typename TT > // Type of the right-hand side matrix +inline bool tryDivAssign( const QuatSlice& lhs, + const Tensor& rhs, size_t k, size_t i, size_t j ) +{ + BLAZE_INTERNAL_ASSERT( k <= lhs.pages(), "Invalid page access index" ); + BLAZE_INTERNAL_ASSERT( k + (~rhs).pages() <= lhs.pages(), "Invalid page range size" ); + BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); + BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); + BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); + BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); + + return tryDivAssign( lhs.operand(), ~rhs, lhs.quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given quatslice. +// \ingroup quatslice +// +// \param r The quatslice to be derestricted. +// \return QuatSlice without access restrictions. +// +// This function removes all restrictions on the data access to the given quatslice. It returns a quatslice +// object that does provide the same interface but does not have any restrictions on the data +// access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< typename AT // Type of the quaternion + , size_t I > // QuatSlice index +inline decltype(auto) derestrict( QuatSlice& r ) +{ + return quatslice( derestrict( r.operand() ), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given temporary quatslice. +// \ingroup quatslice +// +// \param r The temporary quatslice to be derestricted. +// \return QuatSlice without access restrictions. +// +// This function removes all restrictions on the data access to the given temporary quatslice. It +// returns a quatslice object that does provide the same interface but does not have any restrictions +// on the data access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< typename AT // Type of the quaternion + , size_t I > // QuatSlice index +inline decltype(auto) derestrict( QuatSlice&& r ) +{ + return quatslice( derestrict( r.operand() ), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given quatslice. +// \ingroup quatslice +// +// \param r The quatslice to be derestricted. +// \return QuatSlice without access restrictions. +// +// This function removes all restrictions on the data access to the given quatslice. It returns a quatslice +// object that does provide the same interface but does not have any restrictions on the data +// access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< typename AT > // Type of the quaternion +inline decltype(auto) derestrict( QuatSlice& r ) +{ + return quatslice( derestrict( r.operand() ), r.quat(), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Removal of all restrictions on the data access to the given temporary quatslice. +// \ingroup quatslice +// +// \param r The temporary quatslice to be derestricted. +// \return QuatSlice without access restrictions. +// +// This function removes all restrictions on the data access to the given temporary quatslice. It +// returns a quatslice object that does provide the same interface but does not have any restrictions +// on the data access.\n +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in the violation of invariants, erroneous results and/or in compilation errors. +*/ +template< typename AT > // Type of the quaternion +inline decltype(auto) derestrict( QuatSlice&& r ) +{ + return quatslice( derestrict( r.operand() ), r.quat(), unchecked ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct Size< QuatSlice, 0UL > + : public Size +{}; + +template< typename AT, size_t... CRAs > +struct Size< QuatSlice, 1UL > + : public Size +{}; + +template< typename AT, size_t... CRAs > +struct Size< QuatSlice, 2UL > + : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MAXSIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct MaxSize< QuatSlice, 0UL > + : public MaxSize +{}; + +template< typename AT, size_t... CRAs > +struct MaxSize< QuatSlice, 1UL > + : public MaxSize +{}; + +template< typename AT, size_t... CRAs > +struct MaxSize< QuatSlice, 2UL > + : public MaxSize +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct IsRestricted< QuatSlice > + : public IsRestricted +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct HasConstDataAccess< QuatSlice > + : public HasConstDataAccess +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct HasMutableDataAccess< QuatSlice > + : public HasMutableDataAccess +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct IsAligned< QuatSlice > + : public BoolConstant< IsAligned_v > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCONTIGUOUS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct IsContiguous< QuatSlice > + : public IsContiguous +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename AT, size_t... CRAs > +struct IsPadded< QuatSlice > + : public BoolConstant< IsPadded_v > +{}; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/quatslice/BaseTemplate.h b/blaze_tensor/math/views/quatslice/BaseTemplate.h new file mode 100644 index 0000000..4a9fd26 --- /dev/null +++ b/blaze_tensor/math/views/quatslice/BaseTemplate.h @@ -0,0 +1,123 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/views/quatslice/BaseTemplate.h +// \brief Header file for the implementation of the QuatSlice base template +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_BASETEMPLATE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_BASETEMPLATE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include +// #include +#include +// #include +// #include +#include +#include +// #include +// #include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// ::blaze NAMESPACE FORWARD DECLARATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Base template of the QuatSlice class template. +// \ingroup quatslice +*/ +template< typename AT // Type of the 4d array + , size_t... CRAs > // Compile time quatslice arguments +class QuatSlice; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ALIAS DECLARATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary alias declaration for the QuatSlice class template. +// \ingroup quatslice +// +// The QuatSlice_ alias declaration represents a convenient shortcut for the specification of the +// non-derived template arguments of the QuatSlice class template. +*/ +template< typename AT // Type of the 4d array + , size_t... CRAs > // Compile time quatslice arguments +using QuatSlice_ = QuatSlice< AT + , CRAs... >; +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/quatslice/Dense.h b/blaze_tensor/math/views/quatslice/Dense.h new file mode 100644 index 0000000..1cd6983 --- /dev/null +++ b/blaze_tensor/math/views/quatslice/Dense.h @@ -0,0 +1,2050 @@ +//================================================================================================= +/*! +// \file blaze_quaternion/math/views/quatslice/Dense.h +// \brief QuatSlice specialization for dense quaternions +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_DENSE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_DENSE_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR DENSE TENSORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of QuatSlice for quatslices on quatslice-major dense quaternions. +// \ingroup quatslice +// +// This specialization of QuatSlice adapts the class template to the requirements of quatslice-major +// dense quaternions. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +class QuatSlice + : public View< DenseTensor< QuatSlice > > + , private QuatSliceData +{ + private: + //**Type definitions**************************************************************************** + using DataType = QuatSliceData; //!< The type of the QuatSliceData base class. + using Operand = If_t< IsExpression_v, AT, AT& >; //!< Composite data type of the dense quaternion expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + //! Type of this QuatSlice instance. + using This = QuatSlice; + + using BaseType = DenseTensor; //!< Base type of this QuatSlice instance. + using ViewedType = AT; //!< The type viewed by this QuatSlice instance. + using ResultType = QuatSliceTrait_t; //!< Result type for expression template evaluations. + //using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Type of the quatslice elements. + using SIMDType = SIMDTrait_t; //!< SIMD type of the quatslice elements. + using ReturnType = ReturnType_t; //!< Return type for expression template evaluations + using CompositeType = const QuatSlice&; //!< Data type for composite expression templates. + + //! Reference to a constant quatslice value. + using ConstReference = ConstReference_t; + + //! Reference to a non-constant quatslice value. + using Reference = If_t< IsConst_v, ConstReference, Reference_t >; + + //! Pointer to a constant quatslice value. + using ConstPointer = ConstPointer_t; + + //! Pointer to a non-constant quatslice value. + using Pointer = If_t< IsConst_v || !HasMutableDataAccess_v, ConstPointer, Pointer_t >; + + //! Iterator over constant elements. + using ConstIterator = ConstIterator_t; + + //! Iterator over non-constant elements. + using Iterator = If_t< IsConst_v, ConstIterator, Iterator_t >; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = AT::simdEnabled; + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = AT::smpAssignable; + //********************************************************************************************** + + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + template< typename... RRAs > + explicit inline QuatSlice( AT& quaternion, RRAs... args ); + + QuatSlice( const QuatSlice& ) = default; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~QuatSlice() = default; + //@} + //********************************************************************************************** + + //**Data access functions*********************************************************************** + /*!\name Data access functions */ + //@{ + inline Reference operator()( size_t k, size_t i, size_t j ); + inline ConstReference operator()( size_t k, size_t i, size_t j ) const; + inline Reference at( size_t k, size_t i, size_t j ); + inline ConstReference at( size_t k, size_t i, size_t j ) const; + inline Pointer data () noexcept; + inline ConstPointer data () const noexcept; + inline Pointer data ( size_t i, size_t k ) noexcept; + inline ConstPointer data ( size_t i, size_t k ) const noexcept; + inline Iterator begin ( size_t i, size_t k ); + inline ConstIterator begin ( size_t i, size_t k ) const; + inline ConstIterator cbegin( size_t i, size_t k ) const; + inline Iterator end ( size_t i, size_t k ); + inline ConstIterator end ( size_t i, size_t k ) const; + inline ConstIterator cend ( size_t i, size_t k ) const; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + inline QuatSlice& operator=( const ElementType& rhs ); + inline QuatSlice& operator=( initializer_list< initializer_list< initializer_list > > list ); + inline QuatSlice& operator=( const QuatSlice& rhs ); + + template< typename AT2 > inline QuatSlice& operator= ( const Tensor& rhs ); + template< typename AT2 > inline QuatSlice& operator+=( const Tensor& rhs ); + template< typename AT2 > inline QuatSlice& operator-=( const Tensor& rhs ); + template< typename AT2 > inline QuatSlice& operator%=( const Tensor& rhs ); + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + using DataType::quat; + + inline AT& operand() noexcept; + inline const AT& operand() const noexcept; + + inline size_t pages() const noexcept; + inline size_t rows() const noexcept; + inline size_t columns() const noexcept; + inline size_t spacing() const noexcept; + inline size_t capacity() const noexcept; + inline size_t capacity( size_t i, size_t k ) const noexcept; + inline size_t nonZeros() const; + inline size_t nonZeros( size_t i, size_t k ) const; + inline void reset(); + inline void reset( size_t i, size_t k ); + //@} + //********************************************************************************************** + + //**Numeric functions*************************************************************************** + /*!\name Numeric functions */ + //@{ + template< typename Other > inline QuatSlice& scale( const Other& scalar ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename AT2 > + static constexpr bool VectorizedAssign_v = + ( useOptimizedKernels && + simdEnabled && AT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename AT2 > + static constexpr bool VectorizedAddAssign_v = + ( useOptimizedKernels && + simdEnabled && AT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > && + HasSIMDAdd_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename AT2 > + static constexpr bool VectorizedSubAssign_v = + ( useOptimizedKernels && + simdEnabled && AT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > && + HasSIMDSub_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //********************************************************************************************** + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename AT2 > + static constexpr bool VectorizedSchurAssign_v = + ( useOptimizedKernels && + simdEnabled && AT2::simdEnabled && + IsSIMDCombinable_v< ElementType, ElementType_t > && + HasSIMDMult_v< ElementType, ElementType_t > ); + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + static constexpr size_t SIMDSIZE = SIMDTrait::size; + //********************************************************************************************** + + public: + //**Expression template evaluation functions**************************************************** + /*!\name Expression template evaluation functions */ + //@{ + template< typename Other > + inline bool canAlias( const Other* alias ) const noexcept; + + template< typename AT2, size_t... CRAs2 > + inline bool canAlias( const QuatSlice* alias ) const noexcept; + + template< typename Other > + inline bool isAliased( const Other* alias ) const noexcept; + + template< typename AT2, size_t... CRAs2 > + inline bool isAliased( const QuatSlice* alias ) const noexcept; + + inline bool isAligned () const noexcept; + inline bool canSMPAssign() const noexcept; + + BLAZE_ALWAYS_INLINE SIMDType load ( size_t k, size_t i, size_t j ) const noexcept; + BLAZE_ALWAYS_INLINE SIMDType loada( size_t k, size_t i, size_t j ) const noexcept; + BLAZE_ALWAYS_INLINE SIMDType loadu( size_t k, size_t i, size_t j ) const noexcept; + + BLAZE_ALWAYS_INLINE void store ( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept; + BLAZE_ALWAYS_INLINE void storea( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept; + BLAZE_ALWAYS_INLINE void storeu( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept; + BLAZE_ALWAYS_INLINE void stream( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept; + + template< typename AT2 > + inline auto assign( const DenseTensor& rhs ) -> DisableIf_t< VectorizedAssign_v >; + + template< typename AT2 > + inline auto assign( const DenseTensor& rhs ) -> EnableIf_t< VectorizedAssign_v >; + + template< typename AT2 > + inline auto addAssign( const DenseTensor& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; + + template< typename AT2 > + inline auto addAssign( const DenseTensor& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; + + template< typename AT2 > + inline auto subAssign( const DenseTensor& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; + + template< typename AT2 > + inline auto subAssign( const DenseTensor& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; + + template< typename AT2 > + inline auto schurAssign( const DenseTensor& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; + + template< typename AT2 > + inline auto schurAssign( const DenseTensor& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; + + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + Operand quaternion_; //!< The quaternion containing the quatslice. + //@} + //********************************************************************************************** + + //**Friend declarations************************************************************************* + template< typename AT2, size_t... CRAs2 > friend class QuatSlice; + //********************************************************************************************** + + //**Compile time checks************************************************************************* + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( AT ); + //BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( AT ); + //BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( AT ); +// BLAZE_CONSTRAINT_MUST_NOT_BE_SUBTENSOR_TYPE ( AT ); + //BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( AT ); + //BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( AT ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Constructor for quatslices on quatslice-major dense quaternions. +// +// \param quaternion The quaternion containing the quatslice. +// \param args The runtime quatslice arguments. +// \exception std::invalid_argument Invalid quatslice access index. +// +// By default, the provided quatslice arguments are checked at runtime. In case the quatslice is not properly +// specified (i.e. if the specified index is greater than the number of quats of the given quaternion) +// a \a std::invalid_argument exception is thrown. The checks can be skipped by providing the +// optional \a blaze::unchecked argument. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename... RRAs > // Runtime quatslice arguments +inline QuatSlice::QuatSlice( AT& quaternion, RRAs... args ) + : DataType( args... ) // Base class initialization + , quaternion_ ( quaternion ) // The quaternion containing the quatslice +{ + if( !Contains_v< TypeList, Unchecked > ) { + if( quaternion_.quats() <= quat() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid quatslice access index" ); + } + } + else { + BLAZE_USER_ASSERT( quat() < quaternion_.quats(), "Invalid quatslice access index" ); + } +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DATA ACCESS FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subscript operator for the direct access to the quatslice elements. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access index. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::Reference + QuatSlice::operator()( size_t k, size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( k < pages() , "Invalid page access index" ); + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + BLAZE_USER_ASSERT( j < columns(), "Invalid columns access index" ); + + return quaternion_(quat(), k, i, j); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subscript operator for the direct access to the quatslice elements. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return Reference to the accessed value. +// +// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, +// the at() function is guaranteed to perform a check of the given access index. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstReference + QuatSlice::operator()( size_t k, size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( k < pages() , "Invalid page access index" ); + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + BLAZE_USER_ASSERT( j < columns(), "Invalid columns access index" ); + + return const_cast( quaternion_ )(quat(), k, i, j); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Checked access to the quatslice elements. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid quatslice access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access index. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::Reference + QuatSlice::at( size_t k, size_t i, size_t j ) +{ + if( k >= pages() ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid page access index" ); + } + if( i >= rows() ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" ); + } + if( j >= columns() ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" ); + } + return (*this)(k, i, j); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Checked access to the quatslice elements. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return Reference to the accessed value. +// \exception std::out_of_range Invalid quatslice access index. +// +// In contrast to the subscript operator this function always performs a check of the given +// access index. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstReference + QuatSlice::at( size_t k, size_t i, size_t j ) const +{ + if( k >= pages() ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid page access index" ); + } + if( i >= rows() ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" ); + } + if( j >= columns() ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" ); + } + return (*this)(k, i, j); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the quatslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense quatslice. Note that in case +// of a column-major quaternion you can NOT assume that the quatslice elements lie adjacent to each other! +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::Pointer + QuatSlice::data() noexcept +{ + return quaternion_.data( quat(), 0, 0 ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the quatslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense quatslice. Note that in case +// of a column-major quaternion you can NOT assume that the quatslice elements lie adjacent to each other! +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstPointer + QuatSlice::data() const noexcept +{ + return quaternion_.data( quat(), 0, 0 ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the quatslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense quatslice. Note that in case +// of a column-major quaternion you can NOT assume that the quatslice elements lie adjacent to each other! +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::Pointer + QuatSlice::data( size_t i, size_t k ) noexcept +{ + return quaternion_.data( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Low-level data access to the quatslice elements. +// +// \return Pointer to the internal element storage. +// +// This function returns a pointer to the internal storage of the dense quatslice. Note that in case +// of a column-major quaternion you can NOT assume that the quatslice elements lie adjacent to each other! +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstPointer + QuatSlice::data( size_t i, size_t k ) const noexcept +{ + return quaternion_.data( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator to the first element of the quatslice. +// +// \param i The row/column index. +// \return Iterator to the first element of the given row on this quatslice. +// +// This function returns an iterator to the first element of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::Iterator + QuatSlice::begin( size_t i, size_t k ) +{ + return quaternion_.begin( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator to the first element of the quatslice. +// +// \param i The row/column index. +// \return Iterator to the first element of the quatslice. +// +// This function returns an iterator to the first element of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstIterator + QuatSlice::begin( size_t i, size_t k ) const +{ + return quaternion_.cbegin( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator to the first element of the quatslice. +// +// \param i The row/column index. +// \return Iterator to the first element of the quatslice. +// +// This function returns an iterator to the first element of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstIterator + QuatSlice::cbegin( size_t i, size_t k ) const +{ + return quaternion_.cbegin( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator just past the last element of the quatslice. +// +// \param i The row/column index. +// \return Iterator just past the last element of the quatslice. +// +// This function returns an iterator just past the last element of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::Iterator + QuatSlice::end( size_t i, size_t k ) +{ + return quaternion_.end( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator just past the last element of the quatslice. +// +// \param i The row/column index. +// \return Iterator just past the last element of the quatslice. +// +// This function returns an iterator just past the last element of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstIterator + QuatSlice::end( size_t i, size_t k ) const +{ + return quaternion_.cend( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns an iterator just past the last element of the quatslice. +// +// \param i The row/column index. +// \return Iterator just past the last element of the quatslice. +// +// This function returns an iterator just past the last element of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline typename QuatSlice::ConstIterator + QuatSlice::cend( size_t i, size_t k ) const +{ + return quaternion_.cend( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ASSIGNMENT OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Homogeneous assignment to all quatslice elements. +// +// \param rhs Scalar value to be assigned to all quatslice elements. +// \return Reference to the assigned quatslice. +// +// This function homogeneously assigns the given value to all elements of the quatslice. Note that in +// case the underlying dense quaternion is a lower/upper quaternion only lower/upper and diagonal elements +// of the underlying quaternion are modified. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline QuatSlice& + QuatSlice::operator=( const ElementType& rhs ) +{ + decltype(auto) left( derestrict( quaternion_ ) ); + + for( size_t k=0; k || IsTriangular_v || trySet( quaternion_, i, j, k, rhs ) ) + left(quat(),k,i,j) = rhs; + } + } + } + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief List assignment to all quatslice elements. +// +// \param list The initializer list. +// \exception std::invalid_argument Invalid assignment to quatslice. +// \exception std::invalid_argument Invalid assignment to restricted quaternion. +// +// This assignment operator offers the option to directly assign to all elements of the dense +// quatslice by means of an initializer list. The quatslice elements are assigned the values from the given +// initializer list. Missing values are reset to their default state. Note that in case the size +// of the initializer list exceeds the size of the quatslice, a \a std::invalid_argument exception is +// thrown. Also, if the underlying quaternion \a AT is restricted and the assignment would violate +// an invariant of the quaternion, a \a std::invalid_argument exception is thrown. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline QuatSlice& + QuatSlice::operator=( initializer_list< initializer_list< initializer_list > > list ) +{ + if (list.size() > pages() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to quatslice" ); + } + + if( IsRestricted_v ) { + const InitializerTensor tmp( list, rows(), columns() ); + if( !tryAssign( quaternion_, tmp, quat(), 0UL, 0UL, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + } + } + + decltype(auto) left( derestrict( *this ) ); + + size_t k( 0UL ); + for( const auto& colList : list ) { + size_t i( 0UL ); + for( const auto& rowList : colList ) { + std::fill( std::copy( rowList.begin(), rowList.end(), left.begin(i, k) ), left.end(i, k), ElementType() ); + ++i; + } + ++k; + } + + BLAZE_INTERNAL_ASSERT( isIntact( quaternion_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Copy assignment operator for QuatSlice. +// +// \param rhs Dense quatslice to be copied. +// \return Reference to the assigned quatslice. +// \exception std::invalid_argument QuatSlice sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted quaternion. +// +// In case the current sizes of the two quatslices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying quaternion \a AT is a lower or upper triangular quaternion and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline QuatSlice& + QuatSlice::operator=( const QuatSlice& rhs ) +{ + if( &rhs == this ) return *this; + + if( rows() != rhs.rows() || columns() != rhs.columns() || pages() != rhs.pages() ) { + BLAZE_THROW_INVALID_ARGUMENT( "QuatSlice sizes do not match" ); + } + + if( !tryAssign( quaternion_, rhs, quat(), 0UL, 0UL, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsExpression_v && rhs.canAlias( &quaternion_ ) ) { + const ResultType tmp( rhs ); + smpAssign( left, tmp ); + } + else { + smpAssign( left, rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( quaternion_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Assignment operator for different matrices. +// +// \param rhs Tensor to be assigned. +// \return Reference to the assigned quatslice. +// \exception std::invalid_argument Tensor sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted quaternion. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying quaternion \a AT is a lower or upper triangular quaternion and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side matrix +inline QuatSlice& + QuatSlice::operator=( const Tensor& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() || pages() != (~rhs).pages() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Tensor sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const AT2& >; + Right right( ~rhs ); + + if( !tryAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &quaternion_ ) ) { + const ResultType_t tmp( right ); + smpAssign( left, tmp ); + } + else { + //if( IsSparseTensor_v ) + // reset(); + smpAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( quaternion_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Addition assignment operator for the addition of a matrix (\f$ \vec{a}+=\vec{b} \f$). +// +// \param rhs The right-hand side matrix to be added to the dense quatslice. +// \return Reference to the assigned quatslice. +// \exception std::invalid_argument Vector sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted quaternion. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying quaternion \a AT is a lower or upper triangular quaternion and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side matrix +inline QuatSlice& + QuatSlice::operator+=( const Tensor& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() || pages() != (~rhs).pages() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Tensor sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const AT2& >; + Right right( ~rhs ); + + if( !tryAddAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &quaternion_ ) ) { + const ResultType_t tmp( right ); + smpAddAssign( left, tmp ); + } + else { + smpAddAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( quaternion_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ \vec{a}-=\vec{b} \f$). +// +// \param rhs The right-hand side matrix to be subtracted from the dense quatslice. +// \return Reference to the assigned quatslice. +// \exception std::invalid_argument Vector sizes do not match. +// \exception std::invalid_argument Invalid assignment to restricted quaternion. +// +// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception +// is thrown. Also, if the underlying quaternion \a AT is a lower or upper triangular quaternion and the +// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument +// exception is thrown. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side matrix +inline QuatSlice& + QuatSlice::operator-=( const Tensor& rhs ) +{ + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() || pages() != (~rhs).pages() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Tensor sizes do not match" ); + } + + using Right = If_t< IsRestricted_v, CompositeType_t, const AT2& >; + Right right( ~rhs ); + + if( !trySubAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && right.canAlias( &quaternion_ ) ) { + const ResultType_t tmp( right ); + smpSubAssign( left, tmp ); + } + else { + smpSubAssign( left, right ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( quaternion_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Schur product assignment operator for the multiplication of a matrix +// (\f$ \vec{a}\times=\vec{b} \f$). +// +// \param rhs The right-hand side matrix for the cross product. +// \return Reference to the assigned quatslice. +// \exception std::invalid_argument Invalid matrix size for cross product. +// \exception std::invalid_argument Invalid assignment to restricted quaternion. +// +// In case the current size of any of the two matrices is not equal to 3, a \a std::invalid_argument +// exception is thrown. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side matrix +inline QuatSlice& + QuatSlice::operator%=( const Tensor& rhs ) +{ + using blaze::assign; + + //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); + + using SchurType = SchurTrait_t< ResultType, ResultType_t >; + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() || pages() != (~rhs).pages() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Tensor sizes do not match" ); + } + + if( !trySchurAssign( quaternion_, (~rhs), quat(), 0UL, 0UL, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + } + + decltype(auto) left( derestrict( *this ) ); + + if( IsReference_v && (~rhs).canAlias( &quaternion_ ) ) { + const SchurType tmp( *this % (~rhs) ); + smpSchurAssign( left, tmp ); + } + else { + smpSchurAssign( left, ~rhs ); + } + + BLAZE_INTERNAL_ASSERT( isIntact( quaternion_ ), "Invariant violation detected" ); + + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the quaternion containing the quatslice. +// +// \return The quaternion containing the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline AT& QuatSlice::operand() noexcept +{ + return quaternion_; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the quaternion containing the quatslice. +// +// \return The quaternion containing the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline const AT& QuatSlice::operand() const noexcept +{ + return quaternion_; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the current size/dimension of the quatslice. +// +// \return The size of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::pages() const noexcept +{ + return quaternion_.pages(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the current size/dimension of the quatslice. +// +// \return The size of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::rows() const noexcept +{ + return quaternion_.rows(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the current size/dimension of the quatslice. +// +// \return The size of the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::columns() const noexcept +{ + return quaternion_.columns(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the minimum capacity of the quatslice. +// +// \return The minimum capacity of the quatslice. +// +// This function returns the minimum capacity of the quatslice, which corresponds to the current size +// plus padding. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::spacing() const noexcept +{ + return quaternion_.spacing(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the maximum capacity of the dense quatslice. +// +// \return The maximum capacity of the dense quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::capacity() const noexcept +{ + return quaternion_.capacity( quat(), 0UL, 0UL ) * quaternion_.pages() * quaternion_.rows(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the maximum capacity of the dense quatslice. +// +// \return The maximum capacity of the dense quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::capacity( size_t i, size_t k ) const noexcept +{ + return quaternion_.capacity( quat(), k, i ) * quaternion_.pages() * quaternion_.rows(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the number of non-zero elements in the quatslice. +// +// \return The number of non-zero elements in the quatslice. +// +// Note that the number of non-zero elements is always less than or equal to the current number +// of columns of the quaternion containing the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::nonZeros() const +{ + size_t count ( 0 ); + for (size_t k = 0; k < pages(); ++k) { + for (size_t i = 0; i < rows(); ++i) { + count += quaternion_.nonZeros( quat(), k, i ); + } + } + return count; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the number of non-zero elements in the quatslice. +// +// \return The number of non-zero elements in the quatslice. +// +// Note that the number of non-zero elements is always less than or equal to the current number +// of columns of the quaternion containing the quatslice. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline size_t QuatSlice::nonZeros( size_t i, size_t k ) const +{ + return quaternion_.nonZeros( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Reset to the default initial values. +// +// \return void +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline void QuatSlice::reset() +{ + for (size_t k = 0; k < pages(); ++k) { + for (size_t i = 0; i < rows(); ++i) { + quaternion_.reset( quat(), k, i ); + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Reset to the default initial values. +// +// \return void +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline void QuatSlice::reset( size_t i, size_t k ) +{ + quaternion_.reset( quat(), k, i ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// NUMERIC FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Scaling of the quatslice by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$). +// +// \param scalar The scalar value for the quatslice scaling. +// \return Reference to the dense quatslice. +// +// This function scales the quatslice by applying the given scalar value \a scalar to each element +// of the quatslice. For built-in and \c complex data types it has the same effect as using the +// multiplication assignment operator. Note that the function cannot be used to scale a quatslice +// on a lower or upper unitriangular quaternion. The attempt to scale such a quatslice results in a +// compile time error! +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename Other > // Data type of the scalar value +inline QuatSlice& + QuatSlice::scale( const Other& scalar ) +{ + for (size_t k = 0; k < pages(); ++k) { + for (size_t i = 0; i < rows(); ++i) { + for (size_t j = 0; j < columns(); ++j) { + quaternion_(quat(), k, i, j) *= scalar; + } + } + } + return *this; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TEMPLATE EVALUATION FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense quatslice can alias with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense quatslice, \a false if not. +// +// This function returns whether the given address can alias with the dense quatslice. In contrast +// to the isAliased() function this function is allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename Other > // Data type of the foreign expression +inline bool QuatSlice::canAlias( const Other* alias ) const noexcept +{ + return quaternion_.isAliased( alias ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense quatslice can alias with the given dense quatslice \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense quatslice, \a false if not. +// +// This function returns whether the given address can alias with the dense quatslice. In contrast +// to the isAliased() function this function is allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 // Data type of the foreign dense quatslice + , size_t... CRAs2 > // Compile time quatslice arguments of the foreign dense quatslice +inline bool + QuatSlice::canAlias( const QuatSlice* alias ) const noexcept +{ + return quaternion_.isAliased( &alias->quaternion_ ) && ( quat() == alias->quat() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense quatslice is aliased with the given address \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense quatslice, \a false if not. +// +// This function returns whether the given address is aliased with the dense quatslice. In contrast +// to the canAlias() function this function is not allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename Other > // Data type of the foreign expression +inline bool QuatSlice::isAliased( const Other* alias ) const noexcept +{ + return quaternion_.isAliased( alias ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense quatslice is aliased with the given dense quatslice \a alias. +// +// \param alias The alias to be checked. +// \return \a true in case the alias corresponds to this dense quatslice, \a false if not. +// +// This function returns whether the given address is aliased with the dense quatslice. In contrast +// to the canAlias() function this function is not allowed to use compile time expressions to +// optimize the evaluation. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 // Data type of the foreign dense quatslice + , size_t... CRAs2 > // Compile time quatslice arguments of the foreign dense quatslice +inline bool + QuatSlice::isAliased( const QuatSlice* alias ) const noexcept +{ + return quaternion_.isAliased( &alias->quaternion_ ) && ( quat() == alias->quat() ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense quatslice is properly aligned in memory. +// +// \return \a true in case the dense quatslice is aligned, \a false if not. +// +// This function returns whether the dense quatslice is guaranteed to be properly aligned in memory, +// i.e. whether the beginning and the end of the dense quatslice are guaranteed to conform to the +// alignment restrictions of the element type \a Type. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline bool QuatSlice::isAligned() const noexcept +{ + return quaternion_.isAligned(); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns whether the dense quatslice can be used in SMP assignments. +// +// \return \a true in case the dense quatslice can be used in SMP assignments, \a false if not. +// +// This function returns whether the dense quatslice can be used in SMP assignments. In contrast to +// the \a smpAssignable member enumeration, which is based solely on compile time information, +// this function additionally provides runtime information (as for instance the current size +// of the dense quatslice). +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +inline bool QuatSlice::canSMPAssign() const noexcept +{ + return ( pages() * rows() * columns() > SMP_DMATASSIGN_THRESHOLD ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Load of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return The loaded SIMD element. +// +// This function performs a load of a specific SIMD element of the dense quatslice. The index +// must be smaller than the number of quaternion columns. This function must \b NOT be called +// explicitly! It is used internally for the performance optimized evaluation of expression +// templates. Calling this function explicitly might result in erroneous results and/or in +// compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE typename QuatSlice::SIMDType + QuatSlice::load( size_t k, size_t i, size_t j ) const noexcept +{ + return quaternion_.load( quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Aligned load of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return The loaded SIMD element. +// +// This function performs an aligned load of a specific SIMD element of the dense quatslice. +// The index must be smaller than the number of quaternion columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE typename QuatSlice::SIMDType + QuatSlice::loada( size_t k, size_t i, size_t j ) const noexcept +{ + return quaternion_.loada( quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Unaligned load of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \return The loaded SIMD element. +// +// This function performs an unaligned load of a specific SIMD element of the dense quatslice. +// The index must be smaller than the number of quaternion columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE typename QuatSlice::SIMDType + QuatSlice::loadu( size_t k, size_t i, size_t j ) const noexcept +{ + return quaternion_.loadu( quat(), k, i, j ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Store of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs a store a specific SIMD element of the dense quatslice. The index +// must be smaller than the number of quaternion columns. This function must \b NOT be called +// explicitly! It is used internally for the performance optimized evaluation of expression +// templates. Calling this function explicitly might result in erroneous results and/or in +// compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE void + QuatSlice::store( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept +{ + quaternion_.store( quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Aligned store of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned store a specific SIMD element of the dense quatslice. The +// index must be smaller than the number of quaternion columns. This function must \b NOT be +// called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE void + QuatSlice::storea( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept +{ + quaternion_.storea( quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Unligned store of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an unaligned store a specific SIMD element of the dense quatslice. +// The index must be smaller than the number of quaternion columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE void + QuatSlice::storeu( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept +{ + quaternion_.storeu( quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Aligned, non-temporal store of a SIMD element of the dense quatslice. +// +// \param index Access index. The index must be smaller than the number of quaternion columns. +// \param value The SIMD element to be stored. +// \return void +// +// This function performs an aligned, non-temporal store a specific SIMD element of the dense +// quatslice. The index must be smaller than the number of quaternion columns. This function must \b NOT +// be called explicitly! It is used internally for the performance optimized evaluation of +// expression templates. Calling this function explicitly might result in erroneous results +// and/or in compilation errors. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +BLAZE_ALWAYS_INLINE void + QuatSlice::stream( size_t k, size_t i, size_t j, const SIMDType& value ) noexcept +{ + quaternion_.stream( quat(), k, i, j, value ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::assign( const DenseTensor& rhs ) + -> DisableIf_t< VectorizedAssign_v > +{ + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages(), "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows(), "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + const size_t jpos((~rhs).columns() & size_t(-2)); + for (size_t k = 0UL; k < pages(); ++k) + { + for (size_t i = 0UL; i < (~rhs).rows(); ++i) + { + for (size_t j = 0UL; j < jpos; j += 2UL) { + quaternion_(quat(), k, i, j) = (~rhs)(k, i, j); + quaternion_(quat(), k, i, j + 1UL) = (~rhs)(k, i, j + 1UL); + } + if (jpos < (~rhs).columns()) + quaternion_(quat(), k, i, jpos) = (~rhs)(k, i, jpos); + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief SIMD optimized implementation of the assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be assigned. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::assign( const DenseTensor& rhs ) + -> EnableIf_t< VectorizedAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns"); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for( size_t k=0UL; k right((~rhs).begin(i, k)); + + if (useStreaming && cols > (cacheSize / (sizeof(ElementType) * 3UL)) && !(~rhs).isAliased(&quaternion_)) + { + for (; j < jpos; j += SIMDSIZE) { + left.stream(right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; remainder && j < cols; ++j) { + *left = *right; ++left; ++right; + } + } + else + { + for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { + left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j < jpos; j += SIMDSIZE) { + left.store(right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; remainder && j < cols; ++j) { + *left = *right; ++left; ++right; + } + } + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the addition assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be added. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::addAssign( const DenseTensor& rhs ) + -> DisableIf_t< VectorizedAddAssign_v > +{ + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + for (size_t k = 0UL; k < pages(); ++k) { + for (size_t i = 0UL; i < (~rhs).rows(); ++i) { + const size_t jpos((~rhs).columns() & size_t(-2)); + for (size_t j = 0UL; j < jpos; j += 2UL) { + quaternion_(quat(), k, i, j) += (~rhs)(k, i, j); + quaternion_(quat(), k, i, j + 1UL) += (~rhs)(k, i, j + 1UL); + } + if (jpos < (~rhs).columns()) + quaternion_(quat(), k, i, jpos) += (~rhs)(k, i, jpos); + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief SIMD optimized implementation of the addition assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be added. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::addAssign( const DenseTensor& rhs ) + -> EnableIf_t< VectorizedAddAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns"); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for( size_t k=0UL; k right((~rhs).begin(i, k)); + + for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j < jpos; j += SIMDSIZE) { + left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; remainder && j < cols; ++j) { + *left += *right; ++left; ++right; + } + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the subtraction assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be subtracted. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::subAssign( const DenseTensor& rhs ) + -> DisableIf_t< VectorizedSubAssign_v > +{ + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + for (size_t k = 0UL; k < pages(); ++k) { + for (size_t i = 0UL; i < (~rhs).rows(); ++i) { + const size_t jpos((~rhs).columns() & size_t(-2)); + for (size_t j = 0UL; j < jpos; j += 2UL) { + quaternion_(quat(), k, i, j) -= (~rhs)(k, i, j); + quaternion_(quat(), k, i, j + 1UL) -= (~rhs)(k, i, j + 1UL); + } + if (jpos < (~rhs).columns()) + quaternion_(quat(), k, i, jpos) -= (~rhs)(k, i, jpos); + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief SIMD optimized implementation of the subtraction assignment of a dense matrix. +// +// \param rhs The right-hand side dense matrix to be subtracted. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the dense quaternion + , size_t... CRAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::subAssign( const DenseTensor& rhs ) + -> EnableIf_t< VectorizedSubAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns"); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for( size_t k=0UL; k right((~rhs).begin(i, k)); + + for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j < jpos; j += SIMDSIZE) { + left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; remainder && j < cols; ++j) { + *left -= *right; ++left; ++right; + } + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default implementation of the Schur product assignment of a row-major dense matrix. +// +// \param rhs The right-hand side dense matrix for the Schur product. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CSAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::schurAssign( const DenseTensor& rhs ) + -> DisableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + for (size_t k = 0UL; k < pages(); ++k) { + for (size_t i = 0UL; i < (~rhs).rows(); ++i) { + const size_t jpos((~rhs).columns() & size_t(-2)); + for (size_t j = 0UL; j < jpos; j += 2UL) { + quaternion_(quat(), k, i, j) *= (~rhs)(k, i, j); + quaternion_(quat(), k, i, j + 1UL) *= (~rhs)(k, i, j + 1UL); + } + if (jpos < (~rhs).columns()) + quaternion_(quat(), k, i, jpos) *= (~rhs)(k, i, jpos); + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief SIMD optimized implementation of the Schur product assignment of a row-major dense matrix. +// +// \param rhs The right-hand side dense matrix for the Schur product. +// \return void +// +// This function must \b NOT be called explicitly! It is used internally for the performance +// optimized evaluation of expression templates. Calling this function explicitly might result +// in erroneous results and/or in compilation errors. Instead of using this function use the +// assignment operator. +*/ +template< typename AT // Type of the quaternion + , size_t... CSAs > // Compile time quatslice arguments +template< typename AT2 > // Type of the right-hand side dense matrix +inline auto QuatSlice::schurAssign( const DenseTensor& rhs ) + -> EnableIf_t< VectorizedSchurAssign_v > +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( pages() == (~rhs).pages() , "Invalid number of pages" ); + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns"); + + constexpr bool remainder( !IsPadded_v || !IsPadded_v ); + + const size_t cols( columns() ); + + for( size_t k=0UL; k right((~rhs).begin(i, k)); + + for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; j < jpos; j += SIMDSIZE) { + left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; + } + for (; remainder && j < cols; ++j) { + *left *= *right; ++left; ++right; + } + } + } +} +/*! \endcond */ +//************************************************************************************************* + + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/views/quatslice/QuatSlice.h b/blaze_tensor/math/views/quatslice/QuatSlice.h new file mode 100644 index 0000000..1f4dd45 --- /dev/null +++ b/blaze_tensor/math/views/quatslice/QuatSlice.h @@ -0,0 +1,329 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/views/quatslice/QuatSlice.h +// \brief QuatSlice documentation +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_QUATSLICE_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_QUATSLICE_H_ + + +//================================================================================================= +// +// DOXYGEN DOCUMENTATION +// +//================================================================================================= + +//************************************************************************************************* +/*!\defgroup quatslice QuatSlice +// \ingroup views +// +// QuatSlices provide views on a specific quatslice of a dense or sparse tensor. As such, quatslices act as a +// reference to a specific quatslice. This reference is valid and can be used in every way any other +// quatslice matrix can be used as long as the tensor containing the quatslice is not resized or entirely +// destroyed. The quatslice also acts as an alias to the quatslice elements: Changes made to the elements +// (e.g. modifying values, inserting or erasing elements) are immediately visible in the tensor +// and changes made via the tensor are immediately visible in the quatslice. +// +// +// \n \section quatslice_setup Setup of QuatSlices +// +// \image html quatslice.png +// \image latex quatslice.eps "QuatSlice view" width=250pt +// +// A reference to a dense or sparse quatslice can be created very conveniently via the \c quatslice() function. +// It can be included via the header file + + \code + #include + \endcode + +// The quatslice index must be in the range from \f$[0..M-1]\f$, where \c M is the total number of quatslices +// of the tensor, and can be specified both at compile time or at runtime: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + + // Creating a reference to the 1st quatslice of tensor A (compile time index) + auto quatslice1 = quatslice<1UL>( A ); + + // Creating a reference to the 2nd quatslice of tensor A (runtime index) + auto quatslice2 = quatslice( A, 2UL ); + \endcode + +// The \c quatslice() function returns an expression representing the quatslice view. The type of this +// expression depends on the given quatslice arguments, primarily the type of the tensor and the compile +// time arguments. If the type is required, it can be determined via \c decltype specifier: + + \code + using ArrayType = blaze::DynamicArray; + using QuatSliceType = decltype( blaze::quatslice<1UL>( std::declval() ) ); + \endcode + +// The resulting view can be treated as any other quatslice matrix, i.e. it can be assigned to, it can +// be copied from, and it can be used in arithmetic operations. The reference can also be used on +// both sides of an assignment: The quatslice can either be used as an alias to grant write access to a +// specific quatslice of a tensor primitive on the left-hand side of an assignment or to grant read-access +// to a specific quatslice of a tensor primitive or expression on the right-hand side of an assignment. +// The following example demonstrates this in detail: + + \code + blaze::DynamicMatrix x; + blaze::DynamicArray A, B; + // ... Resizing and initialization + + // Setting the 2nd quatslice of tensor A to x + auto quatslice2 = quatslice( A, 2UL ); + quatslice2 = x; + + // Setting the 3rd quatslice of tensor B to x + quatslice( B, 3UL ) = x; + + // Setting x to the 4th quatslice of the result of the tensor multiplication + x = quatslice( A * B, 4UL ); + \endcode + +// \n \section quatslice_element_access Element access +// +// The elements of a quatslice can be directly accessed with the subscript operator: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + + // Creating a view on the 4th quatslice of tensor A + auto quatslice4 = quatslice( A, 4UL ); + + // Setting the 1st element of the dense quatslice, which corresponds + // to the 1st element in the 4th quatslice of tensor A + quatslice4(0, 0) = 2.0; + \endcode + +// The numbering of the quatslice elements is + + \f[\left(\begin{array}{*{5}{c}} + 0 & 1 & 2 & \cdots & N-1 \\ + \end{array}\right),\f] + +// where N is the number of columns of the referenced tensor. Alternatively, the elements of a +// quatslice can be traversed via iterators. Just as with vectors, in case of non-const quatslices, \c begin() +// and \c end() return an iterator, which allows to manipulate the elements, in case of constant +// quatslices an iterator to immutable elements is returned: + + \code + blaze::DynamicArray A( 128UL, 256UL ); + // ... Resizing and initialization + + // Creating a reference to the 31st quatslice of tensor A + auto quatslice31 = quatslice( A, 31UL ); + + // Traversing the elements via iterators to non-const elements + for( auto it=quatslice31.begin(); it!=quatslice31.end(); ++it ) { + *it = ...; // OK; Write access to the dense quatslice value + ... = *it; // OK: Read access to the dense quatslice value. + } + + // Traversing the elements via iterators to const elements + for( auto it=quatslice31.cbegin(); it!=quatslice31.cend(); ++it ) { + *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. + ... = *it; // OK: Read access to the dense quatslice value. + } + \endcode + + \code + blaze::CompressedMatrix A( 128UL, 256UL ); + // ... Resizing and initialization + + // Creating a reference to the 31st quatslice of tensor A + auto quatslice31 = quatslice( A, 31UL ); + + // Traversing the elements via iterators to non-const elements + for( auto it=quatslice31.begin(); it!=quatslice31.end(); ++it ) { + it->value() = ...; // OK: Write access to the value of the non-zero element. + ... = it->value(); // OK: Read access to the value of the non-zero element. + it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. + ... = it->index(); // OK: Read access to the index of the sparse element. + } + + // Traversing the elements via iterators to const elements + for( auto it=quatslice31.cbegin(); it!=quatslice31.cend(); ++it ) { + it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. + ... = it->value(); // OK: Read access to the value of the non-zero element. + it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. + ... = it->index(); // OK: Read access to the index of the sparse element. + } + \endcode + +// \n \section sparse_quatslice_element_insertion Element Insertion +// +// Inserting/accessing elements in a sparse quatslice can be done by several alternative functions. +// The following example demonstrates all options: + + \code + blaze::CompressedMatrix A( 10UL, 100UL ); // Non-initialized 10x100 tensor + + auto quatslice0( quatslice( A, 0UL ) ); // Reference to the 0th quatslice of A + + // The subscript operator provides access to all possible elements of the sparse quatslice, + // including the zero elements. In case the subscript operator is used to access an element + // that is currently not stored in the sparse quatslice, the element is inserted into the quatslice. + quatslice0[42] = 2.0; + + // The second operation for inserting elements is the set() function. In case the element + // is not contained in the quatslice it is inserted into the quatslice, if it is already contained in + // the quatslice its value is modified. + quatslice0.set( 45UL, -1.2 ); + + // An alternative for inserting elements into the quatslice is the insert() function. However, + // it inserts the element only in case the element is not already contained in the quatslice. + quatslice0.insert( 50UL, 3.7 ); + + // A very efficient way to add new elements to a sparse quatslice is the append() function. + // Note that append() requires that the appended element's index is strictly larger than + // the currently largest non-zero index of the quatslice and that the quatslice's capacity is large + // enough to hold the new element. + quatslice0.reserve( 10UL ); + quatslice0.append( 51UL, -2.1 ); + \endcode + +// \n \section quatslice_common_operations Common Operations +// +// A quatslice view can be used like any other quatslice vector. For instance, the current number of quatslice +// elements can be obtained via the \c size() function, the current capacity via the \c capacity() +// function, and the number of non-zero elements via the \c nonZeros() function. However, since +// quatslices are references to specific quatslices of a tensor, several operations are not possible, such as +// resizing and swapping. The following example shows this by means of a dense quatslice view: + + \code + blaze::DynamicArray A( 42UL, 42UL ); + // ... Resizing and initialization + + // Creating a reference to the 2nd quatslice of tensor A + auto quatslice2 = quatslice( A, 2UL ); + + quatslice2.size(); // Returns the number of elements in the quatslice + quatslice2.capacity(); // Returns the capacity of the quatslice + quatslice2.nonZeros(); // Returns the number of non-zero elements contained in the quatslice + + quatslice2.resize( 84UL ); // Compilation error: Cannot resize a single quatslice of a tensor + + auto quatslice3 = quatslice( A, 3UL ); + swap( quatslice2, quatslice3 ); // Compilation error: Swap operation not allowed + \endcode + +// \n \section quatslice_arithmetic_operations Arithmetic Operations +// +// Both dense and sparse quatslices can be used in all arithmetic operations that any other dense or +// sparse quatslice vector can be used in. The following example gives an impression of the use of +// dense quatslices within arithmetic operations. All operations (addition, subtraction, multiplication, +// scaling, ...) can be performed on all possible combinations of dense and sparse quatslices with +// fitting element types: + + \code + blaze::DynamicVector a( 2UL, 2.0 ), b; + blaze::CompressedVector c( 2UL ); + c[1] = 3.0; + + blaze::DynamicArray A( 4UL, 2UL ); // Non-initialized 4x2 tensor + + auto quatslice0( quatslice( A, 0UL ) ); // Reference to the 0th quatslice of A + + quatslice0[0] = 0.0; // Manual initialization of the 0th quatslice of A + quatslice0[1] = 0.0; + quatslice( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st quatslice of A + quatslice( A, 2UL ) = a; // Dense vector initialization of the 2nd quatslice of A + quatslice( A, 3UL ) = c; // Sparse vector initialization of the 3rd quatslice of A + + b = quatslice0 + a; // Dense vector/dense vector addition + b = c + quatslice( A, 1UL ); // Sparse vector/dense vector addition + b = quatslice0 * quatslice( A, 2UL ); // Component-wise vector multiplication + + quatslice( A, 1UL ) *= 2.0; // In-place scaling of the 1st quatslice + b = quatslice( A, 1UL ) * 2.0; // Scaling of the 1st quatslice + b = 2.0 * quatslice( A, 1UL ); // Scaling of the 1st quatslice + + quatslice( A, 2UL ) += a; // Addition assignment + quatslice( A, 2UL ) -= c; // Subtraction assignment + quatslice( A, 2UL ) *= quatslice( A, 0UL ); // Multiplication assignment + + double scalar = quatslice( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors + + A = trans( c ) * quatslice( A, 1UL ); // Outer product between two vectors + \endcode + +// \n \section quatslice_on_column_major_tensor QuatSlices on Column-Major Matrices +// +// Especially noteworthy is that quatslice views can be created for both quatslice-major and column-major +// matrices. Whereas the interface of a quatslice-major tensor only allows to traverse a quatslice directly +// and the interface of a column-major tensor only allows to traverse a column, via views it is +// possible to traverse a quatslice of a column-major tensor or a column of a quatslice-major tensor. For +// instance: + + \code + blaze::DynamicArray A( 64UL, 32UL ); + // ... Resizing and initialization + + // Creating a reference to the 1st quatslice of a column-major tensor A + auto quatslice1 = quatslice( A, 1UL ); + + for( auto it=quatslice1.begin(); it!=quatslice1.end(); ++it ) { + // ... + } + \endcode + +// However, please note that creating a quatslice view on a tensor stored in a column-major fashion +// can result in a considerable performance decrease in comparison to a quatslice view on a tensor +// with quatslice-major storage format. This is due to the non-contiguous storage of the tensor +// elements. Therefore care has to be taken in the choice of the most suitable storage order: + + \code + // Setup of two column-major matrices + blaze::DynamicArray A( 128UL, 128UL ); + blaze::DynamicArray B( 128UL, 128UL ); + // ... Resizing and initialization + + // The computation of the 15th quatslice of the multiplication between A and B ... + blaze::DynamicVector x = quatslice( A * B, 15UL ); + + // ... is essentially the same as the following computation, which multiplies + // the 15th quatslice of the column-major tensor A with B. + blaze::DynamicVector x = quatslice( A, 15UL ) * B; + \endcode + +// Although Blaze performs the resulting vector/tensor multiplication as efficiently as possible +// using a quatslice-major storage order for tensor \c A would result in a more efficient evaluation. +*/ +//************************************************************************************************* + +#endif diff --git a/blaze_tensor/math/views/quatslice/QuatSliceData.h b/blaze_tensor/math/views/quatslice/QuatSliceData.h new file mode 100644 index 0000000..37d1e39 --- /dev/null +++ b/blaze_tensor/math/views/quatslice/QuatSliceData.h @@ -0,0 +1,252 @@ +//================================================================================================= +/*! +// \file blaze_tensor/math/views/quatslice/QuatSliceData.h +// \brief Header file for the implementation of the QuatSliceData class template +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_QUATSLICEDATA_H_ +#define _BLAZE_TENSOR_MATH_VIEWS_QUATSLICE_QUATSLICEDATA_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Auxiliary class template for the data members of the QuatSlice class. +// \ingroup quatslice +// +// The auxiliary QuatSliceData class template represents an abstraction of the data members of the +// QuatSlice class template. The necessary set of data members is selected depending on the number +// of compile time quatslice arguments. +*/ +template< size_t... CRAs > // Compile time quatslice arguments +struct QuatSliceData +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR ZERO COMPILE TIME QUATSLICE INDICES +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the QuatSliceData class template for zero compile time quatslice arguments. +// \ingroup quatslice +// +// This specialization of QuatSliceData adapts the class template to the requirements of zero compile +// time quatslice arguments. +*/ +template<> +struct QuatSliceData<> +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + template< typename... RRAs > + explicit inline QuatSliceData( size_t index, RRAs... args ); + + QuatSliceData( const QuatSliceData& ) = default; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~QuatSliceData() = default; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + QuatSliceData& operator=( const QuatSliceData& ) = delete; + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + inline size_t quat() const noexcept; + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + const size_t quatslice_; //!< The index of the quatslice in the quaternion. + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief The constructor for QuatSliceData. +// +// \param index The index of the quatslice. +// \param args The optional quatslice arguments. +*/ +template< typename... RRAs > // Optional quatslice arguments +inline QuatSliceData<>::QuatSliceData( size_t index, RRAs... args ) + : quatslice_( index ) // The index of the quatslice in the tensor +{ + MAYBE_UNUSED( args... ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the index of the quatslice of the underlying dense tensor. +// +// \return The index of the quatslice. +*/ +inline size_t QuatSliceData<>::quat() const noexcept +{ + return quatslice_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR ONE COMPILE TIME QUATSLICE INDEX +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the QuatSliceData class template for a single compile time quatslice argument. +// \ingroup quatslice +// +// This specialization of QuatSliceData adapts the class template to the requirements of a single +// compile time quatslice argument. +*/ +template< size_t Index > // Compile time quatslice index +struct QuatSliceData +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + template< typename... RRAs > + explicit inline QuatSliceData( RRAs... args ); + + QuatSliceData( const QuatSliceData& ) = default; + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + /*!\name Destructor */ + //@{ + ~QuatSliceData() = default; + //@} + //********************************************************************************************** + + //**Assignment operators************************************************************************ + /*!\name Assignment operators */ + //@{ + QuatSliceData& operator=( const QuatSliceData& ) = delete; + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + static inline constexpr size_t quat() noexcept; + //@} + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief The constructor for QuatSliceData. +// +// \param args The optional quatslice arguments. +*/ +template< size_t Index > // Compile time quatslice index +template< typename... RRAs > // Optional quatslice arguments +inline QuatSliceData::QuatSliceData( RRAs... args ) +{ + MAYBE_UNUSED( args... ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Returns the index of the quatslice of the underlying dense tensor. +// +// \return The index of the quatslice. +*/ +template< size_t Index > // Compile time quatslice index +inline constexpr size_t QuatSliceData::quat() noexcept +{ + return Index; +} +/*! \endcond */ +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h b/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h new file mode 100644 index 0000000..2904526 --- /dev/null +++ b/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h @@ -0,0 +1,467 @@ +//================================================================================================= +/*! +// \file blazetest/mathtest/quatslice/DenseGeneralTest.h +// \brief Header file for the QuatSlice dense general test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZETEST_MATHTEST_QUATSLICE_DENSEGENERALTEST_H_ +#define _BLAZETEST_MATHTEST_QUATSLICE_DENSEGENERALTEST_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace blazetest { + +namespace mathtest { + +namespace quatslice { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Auxiliary class for all tests of the dense general QuatSlice specialization. +// +// This class represents a test suite for the blaze::QuatSlice class template specialization for +// dense general matrices. It performs a series of both compile time as well as runtime tests. +*/ +class DenseGeneralTest +{ + public: + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit DenseGeneralTest(); + // No explicitly declared copy constructor. + //@} + //********************************************************************************************** + + //**Destructor********************************************************************************** + // No explicitly declared destructor. + //********************************************************************************************** + + private: + //**Test functions****************************************************************************** + /*!\name Test functions */ + //@{ + void testConstructors(); + void testAssignment(); + void testAddAssign(); + void testSubAssign(); + void testMultAssign(); + void testSchurAssign(); + void testScaling(); + void testFunctionCall(); + void testAt(); + void testIterator(); + void testNonZeros(); + void testReset(); + void testClear(); + void testIsDefault(); + void testIsSame(); + void testSubtensor(); + //void testRow(); + //void testRows(); + //void testColumn(); + //void testColumns(); + //void testBand(); + + template< typename Type > + void checkSize( const Type& quatslice, size_t expectedSize ) const; + + template< typename Type > + void checkPages( const Type& quaternion, size_t expectedPages ) const; + + template< typename Type > + void checkRows( const Type& quaternion, size_t expectedRows ) const; + + template< typename Type > + void checkColumns( const Type& quaternion, size_t expectedColumns ) const; + + template< typename Type > + void checkQuats( const Type& quaternion, size_t expectedQuats ) const; + + template< typename Type > + void checkCapacity( const Type& object, size_t minCapacity ) const; + + template< typename Type > + void checkNonZeros( const Type& object, size_t expectedNonZeros ) const; + + template< typename Type > + void checkNonZeros( const Type& quaternion, size_t i, size_t k, size_t expectedNonZeros ) const; + //@} + //********************************************************************************************** + + //**Utility functions*************************************************************************** + /*!\name Utility functions */ + //@{ + void initialize(); + //@} + //********************************************************************************************** + + //**Type definitions**************************************************************************** + using AT = blaze::DynamicArray<4, int>; //!< Dynamic quaternion type. + using RT = blaze::QuatSlice; //!< Dense quatslice type for quaternions. + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + //AT quat_; //!< dynamic quaternion. + std::string test_; //!< Label of the currently performed test. + //@} + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + //BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( AT ); + BLAZE_CONSTRAINT_MUST_BE_DENSE_TENSOR_TYPE ( RT ); + BLAZE_CONSTRAINT_MUST_BE_QUATSLICE_TENSOR_TYPE( RT ); + /*! \endcond */ + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Checking the size of the given dense quatslice. +// +// \param quatslice The dense quatslice to be checked. +// \param expectedSize The expected size of the dense quatslice. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the size of the given dense quatslice. In case the actual size does not +// correspond to the given expected size, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense quatslice +void DenseGeneralTest::checkSize( const Type& quatslice, size_t expectedSize ) const +{ + if( size( quatslice ) != expectedSize ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid size detected\n" + << " Details:\n" + << " Size : " << size( quatslice ) << "\n" + << " Expected size: " << expectedSize << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of quatslices of the given dynamic quaternion. +// +// \param quaternion The dynamic quaternion to be checked. +// \param expectedQuatSlices The expected number of rows of the dynamic quaternion. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of rows of the given dynamic quaternion. In case the actual number +// of quatslices does not correspond to the given expected number of quatslices, a \a std::runtime_error +// exception is thrown. +*/ +template< typename Type > // Type of the dynamic quaternion +void DenseGeneralTest::checkPages( const Type& quaternion, size_t expectedRows ) const +{ + if( pages( quaternion ) != expectedRows ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of pages detected\n" + << " Details:\n" + << " Number of pages : " << pages( quaternion ) << "\n" + << " Expected number of pages: " << expectedRows << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of quatslices of the given dynamic quaternion. +// +// \param quaternion The dynamic quaternion to be checked. +// \param expectedQuatSlices The expected number of rows of the dynamic quaternion. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of rows of the given dynamic quaternion. In case the actual number +// of quatslices does not correspond to the given expected number of quatslices, a \a std::runtime_error +// exception is thrown. +*/ +template< typename Type > // Type of the dynamic quaternion +void DenseGeneralTest::checkRows( const Type& quaternion, size_t expectedRows ) const +{ + if( rows( quaternion ) != expectedRows ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of rows detected\n" + << " Details:\n" + << " Number of rows : " << rows( quaternion ) << "\n" + << " Expected number of rows: " << expectedRows << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of columns of the given dynamic quaternion. +// +// \param quaternion The dynamic quaternion to be checked. +// \param expectedColumns The expected number of columns of the dynamic quaternion. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of columns of the given dynamic quaternion. In case the +// actual number of columns does not correspond to the given expected number of columns, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic quaternion +void DenseGeneralTest::checkColumns( const Type& quaternion, size_t expectedColumns ) const +{ + if( columns( quaternion ) != expectedColumns ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of columns detected\n" + << " Details:\n" + << " Number of columns : " << columns( quaternion ) << "\n" + << " Expected number of columns: " << expectedColumns << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of quats of the given dynamic quaternion. +// +// \param quaternion The dynamic quaternion to be checked. +// \param expectedQuats The expected number of columns of the dynamic quaternion. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of quats of the given dynamic quaternion. In case the +// actual number of quats does not correspond to the given expected number of quats, +// a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic quaternion +void DenseGeneralTest::checkQuats( const Type& quaternion, size_t expectedQuats ) const +{ + if( quats( quaternion ) != expectedQuats ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of quats detected\n" + << " Details:\n" + << " Number of quats : " << quats( quaternion ) << "\n" + << " Expected number of quats: " << expectedQuats << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the capacity of the given dense quatslice or dynamic quaternion. +// +// \param object The dense quatslice or dynamic quaternion to be checked. +// \param minCapacity The expected minimum capacity. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the capacity of the given dense quatslice or dynamic quaternion. In case the actual +// capacity is smaller than the given expected minimum capacity, a \a std::runtime_error exception +// is thrown. +*/ +template< typename Type > // Type of the dense quatslice or dynamic quaternion +void DenseGeneralTest::checkCapacity( const Type& object, size_t minCapacity ) const +{ + if( capacity( object ) < minCapacity ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Capacity : " << capacity( object ) << "\n" + << " Expected minimum capacity: " << minCapacity << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements of the given dense quatslice or dynamic quaternion. +// +// \param object The dense quatslice or dynamic quaternion to be checked. +// \param expectedNonZeros The expected number of non-zero elements. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements of the given dense quatslice. In case the +// actual number of non-zero elements does not correspond to the given expected number, a +// \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dense quatslice or dynamic quaternion +void DenseGeneralTest::checkNonZeros( const Type& object, size_t expectedNonZeros ) const +{ + if( nonZeros( object ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements\n" + << " Details:\n" + << " Number of non-zeros : " << nonZeros( object ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( capacity( object ) < nonZeros( object ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( object ) << "\n" + << " Capacity : " << capacity( object ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Checking the number of non-zero elements in a specific quatslice/column of the given dynamic quaternion. +// +// \param quaternion The dynamic quaternion to be checked. +// \param index The quatslice/column to be checked. +// \param expectedNonZeros The expected number of non-zero elements in the specified quatslice/column. +// \return void +// \exception std::runtime_error Error detected. +// +// This function checks the number of non-zero elements in the specified quatslice/column of the +// given dynamic quaternion. In case the actual number of non-zero elements does not correspond +// to the given expected number, a \a std::runtime_error exception is thrown. +*/ +template< typename Type > // Type of the dynamic quaternion +void DenseGeneralTest::checkNonZeros( const Type& quaternion, size_t i, size_t k, size_t expectedNonZeros ) const +{ + if( nonZeros( quaternion, i, k ) != expectedNonZeros ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of non-zero elements in row " << i << " quat " << k << "\n" + << " Details:\n" + << " Number of non-zeros : " << nonZeros( quaternion, i, k ) << "\n" + << " Expected number of non-zeros: " << expectedNonZeros << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( capacity( quaternion, i, k ) < nonZeros( quaternion, i, k ) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid capacity detected in row " << i << " quat " << k << "\n" + << " Details:\n" + << " Number of non-zeros: " << nonZeros( quaternion, i, k ) << "\n" + << " Capacity : " << capacity( quaternion, i, k ) << "\n"; + throw std::runtime_error( oss.str() ); + } +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Testing the functionality of the dense general QuatSlice specialization. +// +// \return void +*/ +void runTest() +{ + DenseGeneralTest(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// MACRO DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Macro for the execution of the QuatSlice dense general test. +*/ +#define RUN_QUATSLICE_DENSEGENERAL_TEST \ + blazetest::mathtest::quatslice::runTest() +/*! \endcond */ +//************************************************************************************************* + +} // namespace quatslice + +} // namespace mathtest + +} // namespace blazetest + +#endif diff --git a/blazetest/src/mathtest/CMakeLists.txt b/blazetest/src/mathtest/CMakeLists.txt index a574667..9bad886 100644 --- a/blazetest/src/mathtest/CMakeLists.txt +++ b/blazetest/src/mathtest/CMakeLists.txt @@ -49,6 +49,7 @@ set(subdirs dynamictensor initializertensor pageslice + quatslice rowslice statictensor subtensor diff --git a/blazetest/src/mathtest/quatslice/CMakeLists.txt b/blazetest/src/mathtest/quatslice/CMakeLists.txt new file mode 100644 index 0000000..4c4b10e --- /dev/null +++ b/blazetest/src/mathtest/quatslice/CMakeLists.txt @@ -0,0 +1,43 @@ +# ================================================================================================= +# +# Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +# Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +# +# This file is part of the Blaze library. You can redistribute it and/or modify it under +# the terms of the New (Revised) BSD License. Redistribution and use in source and binary +# forms, with or without modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# 3. Neither the names of the Blaze development group nor the names of its contributors +# may be used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# ================================================================================================= + +set(category QuatSlice) + +set(tests + IncludeTest +) + +foreach(test ${tests}) + add_blaze_tensor_test(${category}${test} + SOURCES ${test}.cpp + FOLDER "Tests/${category}") +endforeach() diff --git a/blazetest/src/mathtest/quatslice/IncludeTest.cpp b/blazetest/src/mathtest/quatslice/IncludeTest.cpp new file mode 100644 index 0000000..0305615 --- /dev/null +++ b/blazetest/src/mathtest/quatslice/IncludeTest.cpp @@ -0,0 +1,62 @@ +//================================================================================================= +/*! +// \file src/mathtest/quatslice/IncludeTest.cpp +// \brief Source file for the QuatSlice include test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + return EXIT_SUCCESS; +} +//************************************************************************************************* From 9b18d524c9ad744f962aaa1595fdb0da85ec4655 Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Fri, 28 Jun 2019 14:37:40 -0500 Subject: [PATCH 08/14] Removing ArraySlice --- blaze_tensor/math/ArraySlice.h | 157 - blaze_tensor/math/InitializerList.h | 1 + blaze_tensor/math/constraints/ArraySlice.h | 88 - blaze_tensor/math/dense/CustomArray.h | 52 +- blaze_tensor/math/dense/DenseArray.h | 2 +- .../math/expressions/DArrReduceExpr.h | 1376 ----- blaze_tensor/math/traits/ArraySliceTrait.h | 211 - blaze_tensor/math/typetraits/IsArraySlice.h | 168 - blaze_tensor/math/views/ArraySlice.h | 1634 ------ blaze_tensor/math/views/Forward.h | 27 +- blaze_tensor/math/views/QuatSlice.h | 4 +- blaze_tensor/math/views/Subtensor.h | 2 - .../math/views/arrayslice/ArraySlice.h | 328 -- .../math/views/arrayslice/ArraySliceData.h | 251 - .../math/views/arrayslice/BaseTemplate.h | 123 - blaze_tensor/math/views/arrayslice/Dense.h | 2321 -------- blaze_tensor/math/views/quatslice/Dense.h | 12 +- .../mathtest/arrayslice/DenseGeneralTest.h | 432 -- blazetest/src/mathtest/CMakeLists.txt | 1 - .../src/mathtest/arrayslice/CMakeLists.txt | 44 - .../mathtest/arrayslice/DenseGeneralTest.cpp | 5156 ---------------- .../src/mathtest/arrayslice/IncludeTest.cpp | 61 - .../mathtest/quatslice/DenseGeneralTest.cpp | 5222 +++++++++++++++++ 23 files changed, 5274 insertions(+), 12399 deletions(-) delete mode 100644 blaze_tensor/math/ArraySlice.h delete mode 100644 blaze_tensor/math/constraints/ArraySlice.h delete mode 100644 blaze_tensor/math/expressions/DArrReduceExpr.h delete mode 100644 blaze_tensor/math/traits/ArraySliceTrait.h delete mode 100644 blaze_tensor/math/typetraits/IsArraySlice.h delete mode 100644 blaze_tensor/math/views/ArraySlice.h delete mode 100644 blaze_tensor/math/views/arrayslice/ArraySlice.h delete mode 100644 blaze_tensor/math/views/arrayslice/ArraySliceData.h delete mode 100644 blaze_tensor/math/views/arrayslice/BaseTemplate.h delete mode 100644 blaze_tensor/math/views/arrayslice/Dense.h delete mode 100644 blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h delete mode 100644 blazetest/src/mathtest/arrayslice/CMakeLists.txt delete mode 100644 blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp delete mode 100644 blazetest/src/mathtest/arrayslice/IncludeTest.cpp create mode 100644 blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp diff --git a/blaze_tensor/math/ArraySlice.h b/blaze_tensor/math/ArraySlice.h deleted file mode 100644 index a761645..0000000 --- a/blaze_tensor/math/ArraySlice.h +++ /dev/null @@ -1,157 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_tensor/math/ArraySlice.h -// \brief Header file for the complete ArraySlice implementation -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_ARRAYSLICE_H_ -#define _BLAZE_TENSOR_MATH_ARRAYSLICE_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace blaze { - -//================================================================================================= -// -// RAND SPECIALIZATION FOR DENSE ARRAYSLICES -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the Rand class template for dense arrayslices. -// \ingroup random -// -// This specialization of the Rand class randomizes dense arrayslices. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -class Rand< ArraySlice > -{ - public: - //**Randomize functions************************************************************************* - /*!\name Randomize functions */ - //@{ - template< typename RT > - inline void randomize( RT&& arrayslice ) const; - - template< typename RT, typename Arg > - inline void randomize( RT&& arrayslice, const Arg& min, const Arg& max ) const; - //@} - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Randomization of a dense arrayslice. -// -// \param arrayslice The arrayslice to be randomized. -// \return void -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename RT > // Type of the arrayslice -inline void Rand< ArraySlice >::randomize( RT&& arrayslice ) const -{ - using blaze::randomize; - - using ArraySliceType = RemoveReference_t; - - BLAZE_CONSTRAINT_MUST_BE_ARRAYSLICE_TYPE ( ArraySliceType ); - BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ArraySliceType ); - - constexpr size_t N = ArraySliceType::num_dimensions(); - - ArrayForEachGrouped( - arrayslice.dimensions(), [&]( std::array< size_t, N > const& indices ) { - randomize( arrayslice( indices ) ); - } ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Randomization of a dense arrayslice. -// -// \param arrayslice The arrayslice to be randomized. -// \param min The smallest possible value for a arrayslice element. -// \param max The largest possible value for a arrayslice element. -// \return void -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename RT // Type of the arrayslice - , typename Arg > // Min/max argument type -inline void Rand< ArraySlice >::randomize( RT&& arrayslice, const Arg& min, const Arg& max ) const -{ - using blaze::randomize; - - using ArraySliceType = RemoveReference_t; - - BLAZE_CONSTRAINT_MUST_BE_ARRAYSLICE_TYPE ( ArraySliceType ); - BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( ArraySliceType ); - - constexpr size_t N = ArraySliceType::num_dimensions(); - - ArrayForEachGrouped( - arrayslice.dimensions(), [&]( std::array< size_t, N > const& indices ) { - randomize( arrayslice( indices ), min, max ); - } ); -} -/*! \endcond */ -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/InitializerList.h b/blaze_tensor/math/InitializerList.h index 99aa0a0..986ad24 100644 --- a/blaze_tensor/math/InitializerList.h +++ b/blaze_tensor/math/InitializerList.h @@ -42,6 +42,7 @@ //************************************************************************************************* #include +#include namespace blaze { diff --git a/blaze_tensor/math/constraints/ArraySlice.h b/blaze_tensor/math/constraints/ArraySlice.h deleted file mode 100644 index dfe24ec..0000000 --- a/blaze_tensor/math/constraints/ArraySlice.h +++ /dev/null @@ -1,88 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_tensor/math/constraints/ArraySlice.h -// \brief Constraint on the data type -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_CONSTRAINTS_ARRAYSLICE_H_ -#define _BLAZE_TENSOR_MATH_CONSTRAINTS_ARRAYSLICE_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include - - -namespace blaze { - -//================================================================================================= -// -// MUST_BE_PAGESLICE_TYPE CONSTRAINT -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Constraint on the data type. -// \ingroup math_constraints -// -// In case the given data type \a T is not a arrayslice type (i.e. a dense or sparse arrayslice), a compilation -// error is created. -*/ -#define BLAZE_CONSTRAINT_MUST_BE_ARRAYSLICE_TYPE(T) \ - static_assert( ::blaze::IsArraySlice_v, "Non-arrayslice type detected" ) -//************************************************************************************************* - - - - -//================================================================================================= -// -// MUST_NOT_BE_PAGESLICE_TYPE CONSTRAINT -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Constraint on the data type. -// \ingroup math_constraints -// -// In case the given data type \a T is a arrayslice type (i.e. a dense or sparse arrayslice), a compilation -// error is created. -*/ -#define BLAZE_CONSTRAINT_MUST_NOT_BE_ARRAYSLICE_TYPE(T) \ - static_assert( !::blaze::IsArraySlice_v, "ArraySlice type detected" ) -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/dense/CustomArray.h b/blaze_tensor/math/dense/CustomArray.h index 1ad1467..ee6ddd5 100644 --- a/blaze_tensor/math/dense/CustomArray.h +++ b/blaze_tensor/math/dense/CustomArray.h @@ -483,32 +483,32 @@ class CustomArray template< typename MT > inline CustomArray& operator-=( const Array& rhs ); template< typename MT > inline CustomArray& operator%=( const Array& rhs ); - template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > - inline ArraySlice& operator= ( const Vector& m ); - template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > - inline ArraySlice& operator+=( const Vector& m ); - template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > - inline ArraySlice& operator-=( const Vector& m ); - template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > - inline ArraySlice& operator%=( const Vector& m ); - - template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > - inline ArraySlice& operator= ( const Matrix& m ); - template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > - inline ArraySlice& operator+=( const Matrix& m ); - template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > - inline ArraySlice& operator-=( const Matrix& m ); - template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > - inline ArraySlice& operator%=( const Matrix& m ); - - template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > - inline ArraySlice& operator= ( const Tensor& m ); - template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > - inline ArraySlice& operator+=( const Tensor& m ); - template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > - inline ArraySlice& operator-=( const Tensor& m ); - template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > - inline ArraySlice& operator%=( const Tensor& m ); + //template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + //inline ArraySlice& operator= ( const Vector& m ); + //template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + //inline ArraySlice& operator+=( const Vector& m ); + //template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + //inline ArraySlice& operator-=( const Vector& m ); + //template< typename MT, bool TF, size_t M = N, typename = EnableIf_t< M == 1 > > + //inline ArraySlice& operator%=( const Vector& m ); + + //template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + //inline ArraySlice& operator= ( const Matrix& m ); + //template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + //inline ArraySlice& operator+=( const Matrix& m ); + //template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + //inline ArraySlice& operator-=( const Matrix& m ); + //template< typename MT, bool SO, size_t M = N, typename = EnableIf_t< M == 2 > > + //inline ArraySlice& operator%=( const Matrix& m ); + + //template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + //inline ArraySlice& operator= ( const Tensor& m ); + //template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + //inline ArraySlice& operator+=( const Tensor& m ); + //template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + //inline ArraySlice& operator-=( const Tensor& m ); + //template< typename MT, size_t M = N, typename = EnableIf_t< M == 3 > > + //inline ArraySlice& operator%=( const Tensor& m ); //@} //********************************************************************************************** diff --git a/blaze_tensor/math/dense/DenseArray.h b/blaze_tensor/math/dense/DenseArray.h index 1504f44..9e38205 100644 --- a/blaze_tensor/math/dense/DenseArray.h +++ b/blaze_tensor/math/dense/DenseArray.h @@ -72,7 +72,7 @@ // #include #include #include -#include +//#include #include #include // #include diff --git a/blaze_tensor/math/expressions/DArrReduceExpr.h b/blaze_tensor/math/expressions/DArrReduceExpr.h deleted file mode 100644 index f72e570..0000000 --- a/blaze_tensor/math/expressions/DArrReduceExpr.h +++ /dev/null @@ -1,1376 +0,0 @@ -//================================================================================================= -/*! -// \file blaze/math/expressions/DArrReduceExpr.h -// \brief Header file for the dense array reduce expression -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRREDUCEEXPR_H_ -#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRREDUCEEXPR_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace blaze { - -//================================================================================================= -// -// CLASS DEFINITION -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Base template for dense array reduction operations. -// \ingroup dense_array_expression -// -// The ReducedArray class represents the compile time expression for partial reduction operations -// of dense matrices. -*/ -template< typename MT // Type of the dense array - , typename OP // Type of the reduction operation - , size_t RF > // Reduction flag -class ReducedArray; -//************************************************************************************************* - - - - -//================================================================================================= -// -// CLASS TEMPLATE SPECIALIZATION FOR ARBITRARY REDUCTION OPERATIONS OF ARRAYS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Expression object for arbitrary dense array reduction operations. -// \ingroup dense_array_expression -// -// This specialization of the ReducedArray class template represents the compile time expression -// for row-wise reduction operations of dense matrices. -*/ -template< typename MT // Type of the dense array - , typename OP // Type of the reduction operation - , size_t R > // DImension along which to perform reduction -class ReducedArray - : public ArrReduceExpr< DenseArray< ReducedArray >, R > - , private Computation -{ - private: - //**Type definitions**************************************************************************** - using RT = ResultType_t; //!< Result type of the dense array expression. - using ET = ElementType_t; //!< Element type of the dense array expression. - //********************************************************************************************** - - //**Serial evaluation strategy****************************************************************** - //! Compilation switch for the serial evaluation strategy of the reduction expression. - /*! The \a useAssign compile time constant expression represents a compilation switch for - the serial evaluation strategy of the reduction expression. In case the dense array - operand requires an intermediate evaluation, \a useAssign will be set to 1 and the - reduction expression will be evaluated via the \a assign function family. Otherwise - \a useAssign will be set to 0 and the expression will be evaluated via the subscript - operator. */ - static constexpr bool useAssign = RequiresEvaluation_v; - - /*! \cond BLAZE_INTERNAL */ - //! Helper variable template for the explicit application of the SFINAE principle. - template< typename VT > - static constexpr bool UseAssign_v = useAssign; - /*! \endcond */ - //********************************************************************************************** - - //**Parallel evaluation strategy**************************************************************** - /*! \cond BLAZE_INTERNAL */ - //! Helper variable template for the explicit application of the SFINAE principle. - /*! This variable template is a helper for the selection of the parallel evaluation strategy. - In case the dense array operand is not SMP assignable and requires an intermediate - evaluation, the variable is set to 1 and the expression specific evaluation strategy - is selected. Otherwise the variable is set to 0 and the default strategy is chosen. */ - template< typename VT > - static constexpr bool UseSMPAssign_v = ( !MT::smpAssignable && useAssign ); - /*! \endcond */ - //********************************************************************************************** - - public: - //**Type definitions**************************************************************************** - using This = ReducedArray; //!< Type of this ReducedArray instance. - using ResultType = ReduceTrait_t; //!< Result type for expression template evaluations. - using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. - using ElementType = ElementType_t; //!< Resulting element type. - using SIMDType = SIMDTrait_t; //!< Resulting SIMD element type. - using ReturnType = const ElementType; //!< Return type for expression template evaluations. - - //! Data type for composite expression templates. - using CompositeType = If_t< useAssign, const ResultType, const ReducedArray& >; - - //! Composite type of the left-hand side dense array expression. - using Operand = If_t< IsExpression_v, const MT, const MT& >; - - //! Data type of the custom unary operation. - using Operation = OP; - //********************************************************************************************** - - //**ConstIterator class definition************************************************************** - /*!\brief Iterator over the elements of the dense array. - */ - class ConstIterator - { - public: - //**Type definitions************************************************************************* - using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. - using ValueType = ElementType; //!< Type of the underlying elements. - using PointerType = ElementType*; //!< Pointer return type. - using ReferenceType = ElementType&; //!< Reference return type. - using DifferenceType = ptrdiff_t; //!< Difference between two iterators. - - // STL iterator requirements - using iterator_category = IteratorCategory; //!< The iterator category. - using value_type = ValueType; //!< Type of the underlying elements. - using pointer = PointerType; //!< Pointer return type. - using reference = ReferenceType; //!< Reference return type. - using difference_type = DifferenceType; //!< Difference between two iterators. - //******************************************************************************************* - - //**Constructor****************************************************************************** - /*!\brief Constructor for the ConstIterator class. - // - // \param dm The dense array operand of the reduction expression. - // \param i Index to the initial array page. - // \param i Index to the array row. - // \param op The reduction operation. - */ - explicit inline ConstIterator( Operand dm, size_t k, OP op ) - : dm_ ( dm ) // Dense array of the reduction expression - , k_ ( k ) // Index to the current array page - , op_ ( op ) // The reduction operation - {} - //******************************************************************************************* - - //**Addition assignment operator************************************************************* - /*!\brief Addition assignment operator. - // - // \param inc The increment of the iterator. - // \return The incremented iterator. - */ - inline ConstIterator& operator+=( size_t inc ) { - k_ += inc; - return *this; - } - //******************************************************************************************* - - //**Subtraction assignment operator********************************************************** - /*!\brief Subtraction assignment operator. - // - // \param dec The decrement of the iterator. - // \return The decremented iterator. - */ - inline ConstIterator& operator-=( size_t dec ) { - k_ -= dec; - return *this; - } - //******************************************************************************************* - - //**Prefix increment operator**************************************************************** - /*!\brief Pre-increment operator. - // - // \return Reference to the incremented iterator. - */ - inline ConstIterator& operator++() { - ++k_; - return *this; - } - //******************************************************************************************* - - //**Postfix increment operator*************************************************************** - /*!\brief Post-increment operator. - // - // \return The previous position of the iterator. - */ - inline const ConstIterator operator++( int ) { - return ConstIterator( k_++ ); - } - //******************************************************************************************* - - //**Prefix decrement operator**************************************************************** - /*!\brief Pre-decrement operator. - // - // \return Reference to the decremented iterator. - */ - inline ConstIterator& operator--() { - --k_; - return *this; - } - //******************************************************************************************* - - //**Postfix decrement operator*************************************************************** - /*!\brief Post-decrement operator. - // - // \return The previous position of the iterator. - */ - inline const ConstIterator operator--( int ) { - return ConstIterator( k_-- ); - } - //******************************************************************************************* - - //**Element access operator****************************************************************** - /*!\brief Direct access to the element at the current iterator position. - // - // \return The resulting value. - */ - inline ReturnType operator*() const { - return reduce( arrayslice< R >( dm_, k_, unchecked ), op_ ); - } - //******************************************************************************************* - - //**Equality operator************************************************************************ - /*!\brief Equality comparison between two ConstIterator objects. - // - // \param rhs The right-hand side iterator. - // \return \a true if the iterators refer to the same element, \a false if not. - */ - inline bool operator==( const ConstIterator& rhs ) const { - return k_ == rhs.k_; - } - //******************************************************************************************* - - //**Inequality operator********************************************************************** - /*!\brief Inequality comparison between two ConstIterator objects. - // - // \param rhs The right-hand side iterator. - // \return \a true if the iterators don't refer to the same element, \a false if they do. - */ - inline bool operator!=( const ConstIterator& rhs ) const { - return k_ != rhs.k_; - } - //******************************************************************************************* - - //**Less-than operator*********************************************************************** - /*!\brief Less-than comparison between two ConstIterator objects. - // - // \param rhs The right-hand side iterator. - // \return \a true if the left-hand side iterator is smaller, \a false if not. - */ - inline bool operator<( const ConstIterator& rhs ) const { - return k_ < rhs.k_; - } - //******************************************************************************************* - - //**Greater-than operator******************************************************************** - /*!\brief Greater-than comparison between two ConstIterator objects. - // - // \param rhs The right-hand side iterator. - // \return \a true if the left-hand side iterator is greater, \a false if not. - */ - inline bool operator>( const ConstIterator& rhs ) const { - return !(*this <= rhs); - } - //******************************************************************************************* - - //**Less-or-equal-than operator************************************************************** - /*!\brief Less-than comparison between two ConstIterator objects. - // - // \param rhs The right-hand side iterator. - // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. - */ - inline bool operator<=( const ConstIterator& rhs ) const { - return k_ <= rhs.k_; - } - //******************************************************************************************* - - //**Greater-or-equal-than operator*********************************************************** - /*!\brief Greater-than comparison between two ConstIterator objects. - // - // \param rhs The right-hand side iterator. - // \return \a true if the left-hand side iterator is greater or equal, \a false if not. - */ - inline bool operator>=( const ConstIterator& rhs ) const { - return !(*this < rhs); - } - //******************************************************************************************* - - //**Subtraction operator********************************************************************* - /*!\brief Calculating the number of elements between two iterators. - // - // \param rhs The right-hand side iterator. - // \return The number of elements between the two iterators. - */ - inline DifferenceType operator-( const ConstIterator& rhs ) const { - return k_ - rhs.k_; - } - //******************************************************************************************* - - //**Addition operator************************************************************************ - /*!\brief Addition between a ConstIterator and an integral value. - // - // \param it The iterator to be incremented. - // \param inc The number of elements the iterator is incremented. - // \return The incremented iterator. - */ - friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { - return ConstIterator( it.k_ + inc ); - } - //******************************************************************************************* - - //**Addition operator************************************************************************ - /*!\brief Addition between an integral value and a ConstIterator. - // - // \param inc The number of elements the iterator is incremented. - // \param it The iterator to be incremented. - // \return The incremented iterator. - */ - friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { - return ConstIterator( it.k_ + inc ); - } - //******************************************************************************************* - - //**Subtraction operator********************************************************************* - /*!\brief Subtraction between a ConstIterator and an integral value. - // - // \param it The iterator to be decremented. - // \param dec The number of elements the iterator is decremented. - // \return The decremented iterator. - */ - friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { - return ConstIterator( it.k_ - dec ); - } - //******************************************************************************************* - - private: - //**Member variables************************************************************************* - Operand dm_; //!< Dense array of the reduction expression. - size_t k_; //!< Index to the current array page. - OP op_; //!< The reduction operation. - //******************************************************************************************* - }; - //********************************************************************************************** - - //**Compilation flags*************************************************************************** - //! Compilation switch for the expression template evaluation strategy. - static constexpr bool simdEnabled = false; - - //! Compilation switch for the expression template assignment strategy. - static constexpr bool smpAssignable = MT::smpAssignable; - //********************************************************************************************** - - //**Constructor********************************************************************************* - /*!\brief Constructor for the ReducedArray class. - // - // \param dm The array operand of the reduction expression. - // \param op The reduction operation. - */ - explicit inline ReducedArray( const MT& dm, OP op ) noexcept - : dm_( dm ) // Dense array of the reduction expression - , op_( op ) // The reduction operation - {} - //********************************************************************************************** - - //**Subscript operator************************************************************************** - /*!\brief Subscript operator for the direct access to the array elements. - // - // \param index Access index. The index has to be in the range \f$[0..N-1]\f$. - // \return The resulting value. - */ - template< typename... Dims > - inline ReturnType operator()( Dims... dims ) const { - return reduce( arrayslice( dm_, dims..., unchecked ), op_ ); - } - //********************************************************************************************** - - //**At function********************************************************************************* - /*!\brief Checked access to the array elements. - // - // \param index Access index. The index has to be in the range \f$[0..N-1]\f$. - // \return The resulting value. - // \exception std::out_of_range Invalid array access index. - */ - template< typename... Dims > - inline ReturnType at( Dims... dims ) const { - constexpr size_t indices[] = {dims...}; - - ArrayDimForEach( dm_.dimensions(), [&]( size_t i, size_t dim ) { - if( indices[i] >= dim ) { - BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); - } - } ); - return (*this)(dims...); - } - //********************************************************************************************** - - //**Begin function****************************************************************************** - /*!\brief Returns an iterator to the first element of the dense array. - // - // \return Iterator to the first element of the dense array. - */ - inline ConstIterator begin( size_t i ) const { - return ConstIterator( dm_, i, op_ ); - } - //********************************************************************************************** - - //**End function******************************************************************************** - /*!\brief Returns an iterator just past the last non-zero element of the dense array. - // - // \return Iterator just past the last non-zero element of the dense array. - */ - inline ConstIterator end( size_t i ) const { - return ConstIterator( dm_, i, op_ ); - } - //********************************************************************************************** - - //**Num_dimensions function******************************************************************************* - /*!\brief Returns the current number of dimensions of the array. - // - // \return The size of the array. - */ - inline static constexpr size_t num_dimensions() noexcept { - return RemoveCV_t>::num_dimensions(); - } - //********************************************************************************************** - - //**Dimensions function**************************************************************************** - /*!\brief Returns the current dimensions of the array. - // - // \return The dimensions of the array. - */ - inline decltype(auto) dimensions() const noexcept { - return dm_.dimensions(); - } - //********************************************************************************************** - - //**Pages function******************************************************************************* - /*!\brief Returns the current size/dimension of the array. - // - // \return The size of the array. - */ - template< size_t Dim > - inline size_t dimension() const noexcept { - return dm_.template dimension(); - } - //********************************************************************************************** - - //**Operand access****************************************************************************** - /*!\brief Returns the dense array operand. - // - // \return The dense array operand. - */ - inline Operand operand() const noexcept { - return dm_; - } - //********************************************************************************************** - - //**Operation access**************************************************************************** - /*!\brief Returns a copy of the reduction operation. - // - // \return A copy of the reduction operation. - */ - inline Operation operation() const { - return op_; - } - //********************************************************************************************** - - //********************************************************************************************** - /*!\brief Returns whether the expression can alias with the given address \a alias. - // - // \param alias The alias to be checked. - // \return \a true in case an aliasing effect is possible, \a false if not. - */ - template< typename T > - inline bool canAlias( const T* alias ) const noexcept { - return ( dm_.isAliased( alias ) ); - } - //********************************************************************************************** - - //********************************************************************************************** - /*!\brief Returns whether the expression is aliased with the given address \a alias. - // - // \param alias The alias to be checked. - // \return \a true in case the given alias is contained in this expression, \a false if not. - */ - template< typename T > - inline bool isAliased( const T* alias ) const noexcept { - return ( dm_.isAliased( alias ) ); - } - //********************************************************************************************** - - //********************************************************************************************** - /*!\brief Returns whether the operands of the expression are properly aligned in memory. - // - // \return \a true in case the operands are aligned, \a false if not. - */ - inline bool isAligned() const noexcept { - return false; - } - //********************************************************************************************** - - //********************************************************************************************** - /*!\brief Returns whether the expression can be used in SMP assignments. - // - // \return \a true in case the expression can be used in SMP assignments, \a false if not. - */ - inline bool canSMPAssign() const noexcept { - return dm_.canSMPAssign() || ( dimensions<1>() * dimensions<0>() > SMP_DMATREDUCE_THRESHOLD ); - } - //********************************************************************************************** - - private: - //**Member variables**************************************************************************** - Operand dm_; //!< Dense array of the reduction expression. - Operation op_; //!< The reduction operation. - //********************************************************************************************** - - //**Assignment to tensors*********************************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief Assignment of a row-wise dense array reduction operation to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be assigned. - // \return void - // - // This function implements the performance optimized assignment of a row-wise row-major - // dense array reduction expression to a array. Due to the explicit application of the SFINAE - // principle, this function can only be selected by the compiler in case the expression specific - // parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto assign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand - assign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**Addition assignment to tensors************************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief Addition assignment of a row-wise dense array reduction operation to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be added. - // \return void - // - // This function implements the performance optimized addition assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto addAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand - addAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**Subtraction assignment to tensors*********************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief Subtraction assignment of a row-wise dense array reduction operation - // to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be subtracted. - // \return void - // - // This function implements the performance optimized subtraction assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto subAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand - subAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**Multiplication assignment to tensors******************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief Multiplication assignment of a row-wise dense array reduction operation - // to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be multiplied. - // \return void - // - // This function implements the performance optimized multiplication assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto multAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand - multAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**Division assignment to tensors************************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief Division assignment of a row-wise dense array reduction operation to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression divisor. - // \return void - // - // This function implements the performance optimized division assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto divAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand - divAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**SMP assignment to tensors******************************************************************* - /*! \cond BLAZE_INTERNAL */ - /*!\brief SMP assignment of a row-wise dense array reduction operation to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be assigned. - // \return void - // - // This function implements the performance optimized SMP assignment of a row-wise row-major - // dense array reduction expression to a array. Due to the explicit application of the SFINAE - // principle, this function can only be selected by the compiler in case the expression specific - // parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto smpAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseSMPAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand - smpAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**SMP addition assignment to tensors********************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief SMP addition assignment of a row-wise dense array reduction operation - // to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be added. - // \return void - // - // This function implements the performance optimized SMP addition assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto smpAddAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseSMPAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand - smpAddAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**SMP subtraction assignment to tensors******************************************************* - /*! \cond BLAZE_INTERNAL */ - /*!\brief SMP subtraction assignment of a row-wise dense array reduction operation - // to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be subtracted. - // \return void - // - // This function implements the performance optimized SMP subtraction assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto smpSubAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseSMPAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand - smpSubAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**SMP multiplication assignment to tensors**************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief SMP multiplication assignment of a row-wise dense array reduction operation - // to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression to be multiplied. - // \return void - // - // This function implements the performance optimized SMP multiplication assignment of a - // row-wise dense array reduction expression to a array. Due to the explicit - // application of the SFINAE principle, this function can only be selected by the compiler - // in case the expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto smpMultAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseSMPAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand - smpMultAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**SMP division assignment to tensors********************************************************** - /*! \cond BLAZE_INTERNAL */ - /*!\brief SMP division assignment of a row-wise dense array reduction operation - // to a array. - // \ingroup dense_array - // - // \param lhs The target left-hand side array. - // \param rhs The right-hand side reduction expression divisor. - // \return void - // - // This function implements the performance optimized SMP division assignment of a row-wise - // dense array reduction expression to a array. Due to the explicit application - // of the SFINAE principle, this function can only be selected by the compiler in case the - // expression specific parallel evaluation strategy is selected. - */ - template< typename VT1 > // Type of the target dense array - friend inline auto smpDivAssign( Array& lhs, const ReducedArray& rhs ) - -> EnableIf_t< UseSMPAssign_v > - { - BLAZE_FUNCTION_TRACE; - - BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); - - const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand - smpDivAssign( ~lhs, reduce( tmp, rhs.op_ ) ); - } - /*! \endcond */ - //********************************************************************************************** - - //**Compile time checks************************************************************************* - /*! \cond BLAZE_INTERNAL */ - BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); - /*! \endcond */ - //********************************************************************************************** -}; -//================================================================================================= -// -// CLASS DEFINITION -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Auxiliary helper struct for the dense array reduction operation. -// \ingroup dense_array -*/ -template< typename MT // Type of the dense array - , typename OP > // Type of the reduction operation -struct ArrayHelper -{ - //**Type definitions**************************************************************************** - //! Composite type of the dense array expression. - using CT = RemoveReference_t< CompositeType_t >; - - //! Element type of the dense array expression. - using ET = ElementType_t; - - //! Definition of the HasSIMDEnabled type trait. - BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled ); - - //! Definition of the HasLoad type trait. - BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load ); - //********************************************************************************************** - - //********************************************************************************************** - static constexpr bool value = - ( CT::simdEnabled && - If_t< HasSIMDEnabled_v, GetSIMDEnabled, HasLoad >::value ); - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// GLOBAL FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Default backend implementation of the reduction of a dense array. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction computation. -// \param op The reduction operation. -// \return The result of the reduction operation. -// -// This function implements the performance optimized reduction operation for a dense -// array. Due to the explicit application of the SFINAE principle, this function can only be -// selected by the compiler in case vectorization cannot be applied. -*/ -template< typename MT // Type of the dense array - , typename OP > // Type of the reduction operation -inline ElementType_t darrayreduce( const DenseArray& dm, OP op ) -{ - using CT = CompositeType_t; - using ET = ElementType_t; - - constexpr size_t N = - RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); - - std::array< size_t, N > dims{}; - - if( ArrayDimAnyOf( ( ~dm ).dimensions(), - []( size_t, size_t dim ) { return dim == 0; } ) ) - return ET{}; - - if( ArrayDimAllOf( ( ~dm ).dimensions(), - []( size_t, size_t dim ) { return dim == 1; } ) ) - return ( ~dm )( dims ); - - CT tmp( ~dm ); - - BLAZE_INTERNAL_ASSERT( tmp.dimensions() == (~dm).dimensions(), "Invalid number of elements" ); - - ET redux{}; - - ArrayForEachGrouped( ( ~dm ).dimensions(), - [&]( std::array< size_t, N > const& dims ) { - redux = op( redux, tmp( dims ) ); - } ); - - return redux; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Performs a custom reduction operation on the given dense array. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction computation. -// \param op The reduction operation. -// \return The result of the reduction operation. -// -// This function reduces the given dense array \a dm by means of the given reduction operation -// \a op: - - \code - blaze::DynamicArray A; - // ... Resizing and initialization - - const double totalsum1 = reduce( A, blaze::Add() ); - const double totalsum2 = reduce( A, []( double a, double b ){ return a + b; } ); - \endcode - -// As demonstrated in the example it is possible to pass any binary callable as custom reduction -// operation. However, for instance in the case of lambdas the vectorization of the reduction -// operation is compiler dependent and might not perform at peak performance. However, it is also -// possible to create vectorized custom operations. See \ref custom_operations for a detailed -// overview of the possibilities of custom operations. -// -// Please note that the evaluation order of the reduction operation is unspecified. Thus the -// behavior is non-deterministic if \a op is not associative or not commutative. Also, the -// operation is undefined if the given reduction operation modifies the values. -*/ -template< typename MT // Type of the dense array - , typename OP > // Type of the reduction operation -inline decltype(auto) reduce( const DenseArray& dm, OP op ) -{ - BLAZE_FUNCTION_TRACE; - - return darrayreduce( ~dm, op ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Backend implementation for custom reduction operations on dense matrices. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction computation. -// \param op The reduction operation. -// \return The result of the reduction operation. -*/ -template< size_t RF // Reduction flag - , typename MT // Type of the dense array - , typename OP > // Type of the reduction operation -inline const ReducedArray reduce_backend( const DenseArray& dm, OP op ) -{ - return ReducedArray( ~dm, op ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Performs a custom reduction operation on the given dense array. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction computation. -// \param op The reduction operation. -// \return The result of the reduction operation. -// -// This function reduces the rows or columns of the given dense array \a dm by means of the -// given reduction operation \a op. In case the reduction flag \a RF is set to \a blaze::columnwise, -// the elements of the array are reduced column-wise and the result is a row array. In case -// \a RF is set to \a blaze::rowwise, the elements of the array are reduced row-wise and the -// result is a column array: - - \code - using blaze::columnwise; - - blaze::DynamicArray A; - blaze::DynamicMatrix colsum1, colsum2; - // ... Resizing and initialization - - colsum1 = reduce( A, blaze::Add() ); - colsum2 = reduce( A, []( double a, double b ){ return a + b; } ); - \endcode - - \code - using blaze::rowwise; - - blaze::DynamicArray A; - blaze::DynamicMatrix rowsum1, rowsum2; - // ... Resizing and initialization - - rowsum1 = reduce( A, blaze::Add() ); - rowsum2 = reduce( A, []( double a, double b ){ return a + b; } ); - \endcode - -// As demonstrated in the examples it is possible to pass any binary callable as custom reduction -// operation. However, for instance in the case of lambdas the vectorization of the reduction -// operation is compiler dependent and might not perform at peak performance. However, it is also -// possible to create vectorized custom operations. See \ref custom_operations for a detailed -// overview of the possibilities of custom operations. -// -// Please note that the evaluation order of the reduction operation is unspecified. Thus the -// behavior is non-deterministic if \a op is not associative or not commutative. Also, the -// operation is undefined if the given reduction operation modifies the values. -*/ -template< size_t RF // Reduction flag - , typename MT // Type of the dense array - , typename OP > // Type of the reduction operation -inline decltype(auto) reduce( const DenseArray& dm, OP op ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce_backend( ~dm, op ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Reduces the given dense array by means of addition. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction operation. -// \return The result of the reduction operation. -// -// This function reduces the given dense array \a dm by means of addition: - - \code - blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; - - const int totalsum = sum( A ); // Results in 10 - \endcode - -// Please note that the evaluation order of the reduction operation is unspecified. -*/ -template< typename MT > // Type of the dense array -inline decltype(auto) sum( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Add() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Reduces the given dense array by means of addition. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction operation. -// \return The result of the reduction operation. -// -// This function reduces the rows or columns of the given dense array \a dm by means of -// addition. In case the reduction flag \a RF is set to \a blaze::columnwise, the elements of -// the array are reduced column-wise and the result is a row array. In case \a RF is set to -// \a blaze::rowwise, the elements of the array are reduced row-wise and the result is a -// column array: - - \code - using blaze::columnwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix colsum; - - colsum = sum( A ); // Results in ( 2, 3, 6 ) - \endcode - - \code - using blaze::rowwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix rowsum; - - rowsum = sum( A ); // Results in ( 3, 8 ) - \endcode - -// Please note that the evaluation order of the reduction operation is unspecified. -*/ -template< size_t RF // Reduction flag - , typename MT > // Type of the dense array -inline decltype(auto) sum( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Add() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Reduces the given dense array by means of multiplication. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction operation. -// \return The result of the reduction operation. -// -// This function reduces the given dense array \a dm by means of multiplication: - - \code - blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; - - const int totalprod = prod( A ); // Results in 24 - \endcode - -// Please note that the evaluation order of the reduction operation is unspecified. -*/ -template< typename MT > // Type of the dense array -inline decltype(auto) prod( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Mult() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Reduces the given dense array by means of multiplication. -// \ingroup dense_array -// -// \param dm The given dense array for the reduction operation. -// \return The result of the reduction operation. -// -// This function reduces the rows or columns of the given dense array \a dm by means of -// multiplication. In case the reduction flag \a RF is set to \a blaze::columnwise, the elements -// of the array are reduced column-wise and the result is a row array. In case \a RF is set to -// \a blaze::rowwise, the elements of the array are reduced row-wise and the result is a column -// array: - - \code - using blaze::columnwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix colprod; - - colprod = prod( A ); // Results in ( 1, 0, 8 ) - \endcode - - \code - using blaze::rowwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix rowprod; - - rowprod = prod( A ); // Results in ( 0, 12 ) - \endcode - -// Please note that the evaluation order of the reduction operation is unspecified. -*/ -template< size_t RF // Reduction flag - , typename MT > // Type of the dense array -inline decltype(auto) prod( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Mult() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Returns the smallest element of the dense array. -// \ingroup dense_array -// -// \param dm The given dense array. -// \return The smallest dense array element. -// -// This function returns the smallest element of the given dense array. This function can only -// be used for element types that support the smaller-than relationship. In case the given array -// currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in -// case of fundamental data types). - - \code - blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; - - const int totalmin = min( A ); // Results in 1 - \endcode -*/ -template< typename MT > // Type of the dense array -inline decltype(auto) min( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Min() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Returns the smallest element of each row/columns of the dense array. -// \ingroup dense_array -// -// \param dm The given dense array. -// \return The smallest elements in each row/column. -// -// This function returns the smallest element of each row/column of the given dense array \a dm. -// In case the reduction flag \a RF is set to \a blaze::columnwise, a row array containing the -// smallest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a -// column array containing the smallest element of each row is returned. - - \code - using blaze::columnwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix colmin; - - colmin = min( A ); // Results in ( 1, 0, 2 ) - \endcode - - \code - using blaze::rowwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix rowmin; - - rowmin = min( A ); // Results in ( 0, 1 ) - \endcode -*/ -template< size_t RF // Reduction flag - , typename MT > // Type of the dense array -inline decltype(auto) min( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Min() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Returns the largest element of the dense array. -// \ingroup dense_array -// -// \param dm The given dense array. -// \return The largest dense array element. -// -// This function returns the largest element of the given dense array. This function can only -// be used for element types that support the smaller-than relationship. In case the given martix -// currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in -// case of fundamental data types). - - \code - blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; - - const int totalmax = max( A ); // Results in 4 - \endcode -*/ -template< typename MT > // Type of the dense array -inline decltype(auto) max( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Max() ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Returns the largest element of each row/columns of the dense array. -// \ingroup dense_array -// -// \param dm The given dense array. -// \return The largest elements in each row/column. -// -// This function returns the largest element of each row/column of the given dense array \a dm. -// In case the reduction flag \a RF is set to \a blaze::columnwise, a row array containing the -// largest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a -// column array containing the largest element of each row is returned. - - \code - using blaze::columnwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix colmax; - - colmax = max( A ); // Results in ( 1, 3, 4 ) - \endcode - - \code - using blaze::rowwise; - - blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; - blaze::DynamicMatrix rowmax; - - rowmax = max( A ); // Results in ( 2, 4 ) - \endcode -*/ -template< size_t RF // Reduction flag - , typename MT > // Type of the dense array -inline decltype(auto) max( const DenseArray& dm ) -{ - BLAZE_FUNCTION_TRACE; - - return reduce( ~dm, Max() ); -} -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/traits/ArraySliceTrait.h b/blaze_tensor/math/traits/ArraySliceTrait.h deleted file mode 100644 index 3dd5678..0000000 --- a/blaze_tensor/math/traits/ArraySliceTrait.h +++ /dev/null @@ -1,211 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_array/math/traits/ArraySliceTrait.h -// \brief Header file for the arrayslice trait -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_TRAITS_ARRAYSLICETRAIT_H_ -#define _BLAZE_TENSOR_MATH_TRAITS_ARRAYSLICETRAIT_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include - - -namespace blaze { - -//================================================================================================= -// -// CLASS DEFINITION -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t, typename, size_t... > struct ArraySliceTrait; -template< size_t, typename, size_t, typename = void > struct ArraySliceTraitEval1; -template< size_t, typename, size_t, typename = void > struct ArraySliceTraitEval2; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, size_t I, typename T > -auto evalArraySliceTrait( T& ) - -> typename ArraySliceTraitEval1::Type; - -template< size_t M, typename T > -auto evalArraySliceTrait( T& ) - -> typename ArraySliceTraitEval2::Type; - -template< size_t M, size_t I, typename T > -auto evalArraySliceTrait( const T& ) - -> typename ArraySliceTrait::Type; - -template< size_t M, typename T > -auto evalArraySliceTrait( const T& ) - -> typename ArraySliceTrait::Type; - -template< size_t M, size_t I, typename T > -auto evalArraySliceTrait( const volatile T& ) - -> typename ArraySliceTrait::Type; - -template< size_t M, typename T > -auto evalArraySliceTrait( const volatile T& ) - -> typename ArraySliceTrait::Type; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Base template for the ArraySliceTrait class. -// \ingroup math_traits -// -// \section pagetrait_general General -// -// The ArraySliceTrait class template offers the possibility to select the resulting data type when -// creating a view on a specific page of a dense or sparse array. ArraySliceTrait defines the nested -// type \a Type, which represents the resulting data type of the page operation. In case the -// given data type is not a dense or sparse array type, the resulting data type \a Type is -// set to \a INVALID_TYPE. Note that \a const and \a volatile qualifiers and reference modifiers -// are generally ignored. -// -// -// \section pagetrait_specializations Creating custom specializations -// -// Per default, ArraySliceTrait supports all array types of the Blaze library (including views and -// adaptors). For all other data types it is possible to specialize the ArraySliceTrait template. The -// following example shows the according specialization for the DynamicArray class template: - - \code - template< size_t M, typename T1, size_t... CRAs > - struct ArraySliceTrait< M, DynamicArray, CRAs... > - { - using Type = DynamicArray; - }; - \endcode - -// \n \section arrayslicetrait_examples Examples -// -// The following example demonstrates the use of the ArraySliceTrait template, where depending on -// the given array type the resulting page type is selected: - - \code - // Definition of the page type of a dynamic array - using ArrayType1 = blaze::DynamicArray<3,int>; - using ResultType1 = typename blaze::ArraySliceTrait<3,ArrayType1>::Type; - \endcode -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time page arguments -struct ArraySliceTrait -{ - public: - //********************************************************************************************** - /*! \cond BLAZE_INTERNAL */ - using Type = decltype( evalArraySliceTrait( std::declval() ) ); - /*! \endcond */ - //********************************************************************************************** -}; -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Auxiliary alias declaration for the ArraySliceTrait type trait. -// \ingroup math_traits -// -// The ArraySliceTrait_t alias declaration provides a convenient shortcut to access the nested -// \a Type of the ArraySliceTrait class template. For instance, given the array type \a MT the -// following two type definitions are identical: - - \code - using Type1 = typename blaze::ArraySliceTrait::Type; - using Type2 = blaze::ArraySliceTrait_t; - \endcode -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time page arguments -using ArraySliceTrait_t = typename ArraySliceTrait::Type; -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief First auxiliary helper struct for the ArraySliceTrait type trait. -// \ingroup math_traits -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t I // Compile time dimensional index - , typename > // Restricting condition -struct ArraySliceTraitEval1 -{ - public: - //********************************************************************************************** - using Type = typename ArraySliceTraitEval2::Type; - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Second auxiliary helper struct for the ArraySliceTrait type trait. -// \ingroup math_traits -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t I // Compile time dimensional index - , typename > // Restricting condition -struct ArraySliceTraitEval2 -{ - public: - //********************************************************************************************** - using Type = INVALID_TYPE; - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/typetraits/IsArraySlice.h b/blaze_tensor/math/typetraits/IsArraySlice.h deleted file mode 100644 index b5e4705..0000000 --- a/blaze_tensor/math/typetraits/IsArraySlice.h +++ /dev/null @@ -1,168 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_tensor/math/typetraits/IsArraySlice.h -// \brief Header file for the IsArraySlice type trait -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAYSLICE_H_ -#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAYSLICE_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include - -#include - -namespace blaze { - -//================================================================================================= -// -// CLASS DEFINITION -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Compile time check for arrayslices. -// \ingroup math_type_traits -// -// This type trait tests whether or not the given template parameter is a arrayslice (i.e. a view on a -// arrayslice of a dense or sparse matrix). In case the type is a arrayslice, the \a value member constant is -// set to \a true, the nested type definition \a Type is \a TrueType, and the class derives from -// \a TrueType. Otherwise \a value is set to \a false, \a Type is \a FalseType, and the class -// derives from \a FalseType. - - \code - using blaze::aligned; - - using MatrixType1 = blaze::StaticMatrix; - using MatrixType2 = blaze::DynamicArray<3, double>; - using MatrixType3 = blaze::CompressedMatrix; - - MatrixType1 A; - MatrixType2 B( 100UL, 200UL ); - MatrixType3 C( 200UL, 250UL ); - - using ArraySliceType1 = decltype( blaze::arrayslice<1, 4UL>( A ) ); - using ArraySliceType2 = decltype( blaze::arrayslice<1>( B, 16UL ) ); - using ArraySliceType3 = decltype( blaze::arrayslice<1>( C, 17UL ) ); - - blaze::IsArraySlice< 1, ArraySliceType1 >::value // Evaluates to 1 - blaze::IsArraySlice< 1, const ArraySliceType2 >::Type // Results in TrueType - blaze::IsArraySlice< 1, volatile ArraySliceType3 > // Is derived from TrueType - blaze::IsArraySlice< 1, MatrixType1 >::value // Evaluates to 0 - blaze::IsArraySlice< 1, const MatrixType2 >::Type // Results in FalseType - blaze::IsArraySlice< 1, volatile MatrixType3 > // Is derived from FalseType - \endcode -*/ -template< typename T > -struct IsArraySlice - : public FalseType -{}; -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the IsArraySlice type trait for 'ArraySlice'. -// \ingroup math_type_traits -*/ -template< size_t M, typename MT, size_t... CRAs > -struct IsArraySlice< ArraySlice > - : public TrueType -{}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the IsArraySlice type trait for 'const ArraySlice'. -// \ingroup math_type_traits -*/ -template< size_t M, typename MT, size_t... CRAs > -struct IsArraySlice< const ArraySlice > - : public TrueType -{}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the IsArraySlice type trait for 'volatile ArraySlice'. -// \ingroup math_type_traits -*/ -template< size_t M, typename MT, size_t... CRAs > -struct IsArraySlice< volatile ArraySlice > - : public TrueType -{}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the IsArraySlice type trait for 'const volatile ArraySlice'. -// \ingroup math_type_traits -*/ -template< size_t M, typename MT, size_t... CRAs > -struct IsArraySlice< const volatile ArraySlice > - : public TrueType -{}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Auxiliary variable template for the IsArraySlice type trait. -// \ingroup type_traits -// -// The IsArraySlice_v variable template provides a convenient shortcut to access the nested \a value -// of the IsArraySlice class template. For instance, given the type \a T the following two statements -// are identical: - - \code - constexpr bool value1 = blaze::IsArraySlice<3,T>::value; - constexpr bool value2 = blaze::IsArraySlice_v<4,T>; - \endcode -*/ -template< typename T > -constexpr bool IsArraySlice_v = IsArraySlice::value; -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/views/ArraySlice.h b/blaze_tensor/math/views/ArraySlice.h deleted file mode 100644 index 2a4ad48..0000000 --- a/blaze_tensor/math/views/ArraySlice.h +++ /dev/null @@ -1,1634 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_array/math/views/ArraySlice.h -// \brief Header file for the implementation of the ArraySlice view -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_H_ -#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// #include -#include -// #include -// #include -// #include -#include -#include -#include -#include -// #include -// #include -// #include -#include -#include -#include -#include -#include -#include -#include - -namespace blaze { - -//================================================================================================= -// -// GLOBAL FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Creating a view on a specific arrayslice of the given array. -// \ingroup arrayslice -// -// \param array The array containing the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the array. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given array. - - \code - blaze::DynamicArray D; - blaze::CompressedArray S; - // ... Resizing and initialization - - // Creating a view on the 3rd arrayslice of the dense array D along dimension 0 - auto arrayslice3 = arrayslice<0UL,3UL>( D ); - - // Creating a view on the 4th arrayslice of the sparse array S along dimension 2 - auto arrayslice4 = arrayslice<2UL,4UL>( S ); - \page() - -// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly -// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices -// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped -// by providing the optional \a blaze::unchecked argument. - - \code - auto arrayslice3 = arrayslice<0UL,3UL>( D, unchecked ); - auto arrayslice4 = arrayslice<0UL,4UL>( S, unchecked ); - \page() -*/ -template< size_t M // ArraySlice dimension - , size_t I // ArraySlice index - , typename MT // Type of the array - , typename... RRAs > // Optional arrayslice arguments -inline decltype(auto) arrayslice( Array& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - using ReturnType = ArraySlice_; - return ReturnType( ~array, args... ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Creating a view on a specific arrayslice of the given constant array. -// \ingroup arrayslice -// -// \param array The constant array containing the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the array. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given constant -// array. - - \code - - const blaze::DynamicArray D( ... ); - const blaze::CompressedArray S( ... ); - - // Creating a view on the 3rd arrayslice of the dense array D - auto arrayslice3 = arrayslice<0UL,3UL>( D ); - - // Creating a view on the 4th arrayslice of the sparse array S - auto arrayslice4 = arrayslice<0UL,4UL>( S ); - \page() - -// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly -// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices -// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped -// by providing the optional \a blaze::unchecked argument. - - \code - auto arrayslice3 = arrayslice<0UL,3UL>( D, unchecked ); - auto arrayslice4 = arrayslice<0UL,4UL>( S, unchecked ); - \page() -*/ -template< size_t M // ArraySlice dimension - , size_t I // ArraySlice index - , typename MT // Type of the array - , typename... RRAs > // Optional arrayslice arguments -inline decltype(auto) arrayslice( const Array& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - using ReturnType = const ArraySlice_; - return ReturnType( ~array, args... ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Creating a view on a specific arrayslice of the given temporary array. -// \ingroup arrayslice -// -// \param array The temporary array containing the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the array. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given temporary -// array. In case the arrayslice is not properly specified (i.e. if the specified index is greater -// than or equal to the total number of the arrayslices in the given array) a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // ArraySlice dimension - , size_t I // ArraySlice index - , typename MT // Type of the array - , typename... RRAs > // Optional arrayslice arguments -inline decltype(auto) arrayslice( Array&& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - using ReturnType = ArraySlice_; - return ReturnType( ~array, args... ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Creating a view on a specific arrayslice of the given array. -// \ingroup arrayslice -// -// \param array The array containing the arrayslice. -// \param index The index of the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the array. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given array. - - \code - blaze::DynamicArray D; - blaze::CompressedArray S; - // ... Resizing and initialization - - // Creating a view on the 3rd arrayslice of the dense array D along dimension 1 - auto arrayslice3 = arrayslice<1UL>( D, 3UL ); - - // Creating a view on the 4th arrayslice of the sparse array S along dimension 2 - auto arrayslice4 = arrayslice<2UL>( S, 4UL ); - \page() - -// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly -// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices -// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped -// by providing the optional \a blaze::unchecked argument. - - \code - auto arrayslice3 = arrayslice<0UL>( D, 3UL, unchecked ); - auto arrayslice4 = arrayslice<0UL>( S, 4UL, unchecked ); - \page() -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , typename... RRAs > // Optional arrayslice arguments -inline decltype(auto) arrayslice( Array& array, size_t index, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - using ReturnType = ArraySlice_; - return ReturnType( ~array, index, args... ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Creating a view on a specific arrayslice of the given constant array. -// \ingroup arrayslice -// -// \param array The constant array containing the arrayslice. -// \param index The index of the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the array. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given constant -// array. - - \code - const blaze::DynamicArray D( ... ); - const blaze::CompressedArray S( ... ); - - // Creating a view on the 3rd arrayslice of the dense array D - auto arrayslice3 = arrayslice( D, 3UL ); - - // Creating a view on the 4th arrayslice of the sparse array S - auto arrayslice4 = arrayslice( S, 4UL ); - \page() - -// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly -// specified (i.e. if the specified index is greater than or equal to the total number of the arrayslices -// in the given array) a \a std::invalid_argument exception is thrown. The checks can be skipped -// by providing the optional \a blaze::unchecked argument. - - \code - auto arrayslice3 = arrayslice( D, 3UL, unchecked ); - auto arrayslice4 = arrayslice( S, 4UL, unchecked ); - \page() -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , typename... RRAs > // Optional arrayslice arguments -inline decltype(auto) arrayslice( const Array& array, size_t index, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - using ReturnType = const ArraySlice_; - return ReturnType( ~array, index, args... ); -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Creating a view on a specific arrayslice of the given temporary array. -// \ingroup arrayslice -// -// \param array The temporary array containing the arrayslice. -// \param index The index of the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the array. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given temporary -// array. In case the arrayslice is not properly specified (i.e. if the specified index is greater -// than or equal to the total number of the arrayslices in the given array) a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , typename... RRAs > // Optional arrayslice arguments -inline decltype(auto) arrayslice( Array&& array, size_t index, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - using ReturnType = ArraySlice_; - return ReturnType( ~array, index, args... ); -} -//************************************************************************************************* - - - - -//================================================================================================= -// -// GLOBAL RESTRUCTURING FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array/array addition. -// \ingroup arrayslice -// -// \param array The constant array/array addition. -// \param args The runtime arrayslice arguments. -// \return View on the specified arrayslice of the addition. -// -// This function returns an expression representing the specified arrayslice of the given array/array -// addition. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const ArrArrAddExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( (~array).leftOperand(), args... ) + -// arrayslice( (~array).rightOperand(), args... ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array/array subtraction. -// \ingroup arrayslice -// -// \param array The constant array/array subtraction. -// \param args The runtime arrayslice arguments. -// \return View on the specified arrayslice of the subtraction. -// -// This function returns an expression representing the specified arrayslice of the given array/array -// subtraction. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const ArrArrSubExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( (~array).leftOperand(), args... ) - -// arrayslice( (~array).rightOperand(), args... ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given Schur product. -// \ingroup arrayslice -// -// \param array The constant Schur product. -// \param args The runtime arrayslice arguments. -// \return View on the specified arrayslice of the Schur product. -// -// This function returns an expression representing the specified arrayslice of the given Schur product. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const SchurExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( (~array).leftOperand(), args... ) * -// arrayslice( (~array).rightOperand(), args... ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array/array multiplication. -// \ingroup arrayslice -// -// \param array The constant array/array multiplication. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the multiplication. -// -// This function returns an expression representing the specified arrayslice of the given array/array -// multiplication. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const ArrArrMultExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( (~array).leftOperand(), args... ) * (~array).rightOperand(); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given outer product. -// \ingroup arrayslice -// -// \param array The constant outer product. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the outer product. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given outer product. -*/ -// template< size_t I // ArraySlice index -// , typename MT // Array base type of the expression -// , typename... RRAs > // Optional arrayslice arguments -// inline decltype(auto) arrayslice( const VecTVecMultExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// MAYBE_UNUSED( args... ); -// -// if( !Contains_v< TypeList, Unchecked > ) { -// if( (~array).arrayslices() <= I ) { -// BLAZE_THARRAYSLICE_INVALID_ARGUMENT( "Invalid arrayslice access index" ); -// } -// } -// -// return (~array).leftOperand()[I] * (~array).rightOperand(); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given outer product. -// \ingroup arrayslice -// -// \param array The constant outer product. -// \param index The index of the arrayslice. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the outer product. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// This function returns an expression representing the specified arrayslice of the given outer product. -*/ -// template< typename MT // Array base type of the expression -// , typename... RRAs > // Optional arrayslice arguments -// inline decltype(auto) arrayslice( const VecTVecMultExpr& array, size_t index, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// MAYBE_UNUSED( args... ); -// -// if( !Contains_v< TypeList, Unchecked > ) { -// if( (~array).arrayslices() <= index ) { -// BLAZE_THARRAYSLICE_INVALID_ARGUMENT( "Invalid arrayslice access index" ); -// } -// } -// -// return (~array).leftOperand()[index] * (~array).rightOperand(); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array/scalar multiplication. -// \ingroup arrayslice -// -// \param array The constant array/scalar multiplication. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the multiplication. -// -// This function returns an expression representing the specified arrayslice of the given array/scalar -// multiplication. -*/ -template< size_t... CRAs // Compile time arrayslice arguments - , typename MT // Array base type of the expression - , typename... RRAs > // Runtime arrayslice arguments -inline decltype(auto) arrayslice( const ArrScalarMultExpr& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - return arrayslice( (~array).leftOperand(), args... ) * (~array).rightOperand(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array/scalar division. -// \ingroup arrayslice -// -// \param array The constant array/scalar division. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the division. -// -// This function returns an expression representing the specified arrayslice of the given array/scalar -// division. -*/ -template< size_t... CRAs // Compile time arrayslice arguments - , typename MT // Array base type of the expression - , typename... RRAs > // Runtime arrayslice arguments -inline decltype(auto) arrayslice( const ArrScalarDivExpr& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - return arrayslice( (~array).leftOperand(), args... ) / (~array).rightOperand(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given unary array map operation. -// \ingroup arrayslice -// -// \param array The constant unary array map operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the unary map operation. -// -// This function returns an expression representing the specified arrayslice of the given unary array -// map operation. -*/ -template< size_t... CRAs // Compile time arrayslice arguments - , typename MT // Array base type of the expression - , typename... RRAs > // Runtime arrayslice arguments -inline decltype(auto) arrayslice( const ArrMapExpr& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - return map( arrayslice( (~array).operand(), args... ), (~array).operation() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given binary array map operation. -// \ingroup arrayslice -// -// \param array The constant binary array map operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the binary map operation. -// -// This function returns an expression representing the specified arrayslice of the given binary array -// map operation. -*/ -template< size_t... CRAs // Compile time arrayslice arguments - , typename MT // Array base type of the expression - , typename... RRAs > // Runtime arrayslice arguments -inline decltype(auto) arrayslice( const ArrArrMapExpr& array, RRAs... args ) -{ - BLAZE_FUNCTION_TRACE; - - return map( arrayslice( (~array).leftOperand(), args... ), - arrayslice( (~array).rightOperand(), args... ), - (~array).operation() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array evaluation operation. -// \ingroup arrayslice -// -// \param array The constant array evaluation operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the evaluation operation. -// -// This function returns an expression representing the specified arrayslice of the given array -// evaluation operation. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const ArrEvalExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return eval( arrayslice( (~array).operand(), args... ) ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array serialization operation. -// \ingroup arrayslice -// -// \param array The constant array serialization operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the serialization operation. -// -// This function returns an expression representing the specified arrayslice of the given array -// serialization operation. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const ArrSerialExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return serial( arrayslice( (~array).operand(), args... ) ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array declaration operation. -// \ingroup arrayslice -// -// \param array The constant array declaration operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the declaration operation. -// -// This function returns an expression representing the specified arrayslice of the given array -// declaration operation. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const DeclExpr& array, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( (~array).operand(), args... ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array transpose operation. -// \ingroup arrayslice -// -// \param array The constant array transpose operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the transpose operation. -// -// This function returns an expression representing the specified arrayslice of the given array -// transpose operation. -*/ -// template< size_t MK // Compile time arrayslice arguments -// , size_t MI -// , size_t MJ -// , typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arguments -// inline decltype(auto) arrayslice( const ArrTransExpr& array, size_t index, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( evaluate( ~array ), index, args... ); -// } -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given array transpose operation. -// \ingroup arrayslice -// -// \param array The constant array transpose operation. -// \param args The runtime arrayslice arguments -// \return View on the specified arrayslice of the transpose operation. -// -// This function returns an expression representing the specified arrayslice of the given array -// transpose operation. -*/ -// template< typename MT // Array base type of the expression -// , typename... RRAs > // Runtime arguments -// inline decltype(auto) arrayslice( const ArrTransExpr& array, size_t index, RRAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return arrayslice( evaluate( ~array ), index, args... ); -// } -/*! \endcond */ -//************************************************************************************************* - - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a specific arrayslice of the given matrix expansion operation. -// \ingroup subarray -// -// \param array The constant matrix expansion operation. -// \param args Optional arrayslice arguments. -// \return View on the specified arrayslice of the expansion operation. -// -// This function returns an expression representing the specified arrayslice of the given matrix -// expansion operation. -*/ -// template< size_t... CRAs // Compile time arrayslice arguments -// , typename MT // Matrix base type of the expression -// , size_t... CEAs // Compile time expansion arguments -// , typename... RSAs > // Runtime arrayslice arguments -// inline decltype(auto) arrayslice( const MatExpandExpr& array, RSAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// MAYBE_UNUSED( args... ); -// -// return submatrix( (~array).operand(), 0UL, 0UL, (~array).rows(), (~array).columns() ); -// } -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// GLOBAL RESTRUCTURING FUNCTIONS (ROW) -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Creating a view on a selection of row of the given array/vector multiplication. -// \ingroup arrayslice -// -// \param matrix The constant array/vector multiplication. -// \param args The runtime element arguments. -// \return View on the specified row of the multiplication. -// -// This function returns an expression representing the specified elements of the given -// matrix/vector multiplication. -*/ -// template< size_t... CEAs // Compile time element arguments -// , typename MT // Matrix base type of the expression -// , typename... REAs > // Runtime element arguments -// inline decltype(auto) row( const ArrVecMultExpr& matrix, REAs... args ) -// { -// BLAZE_FUNCTION_TRACE; -// -// return trans(arrayslice( (~matrix).leftOperand(), args... ) * (~matrix).rightOperand()); -// } -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ARRAYSLICE OPERATORS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Resetting the given arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The arrayslice to be resetted. -// \return void -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time arrayslice arguments -inline void reset( ArraySlice& arrayslice ) -{ - arrayslice.reset(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Resetting the given temporary arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The temporary arrayslice to be resetted. -// \return void -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time arrayslice arguments -inline void reset( ArraySlice&& arrayslice ) -{ - arrayslice.reset(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Clearing the given arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The arrayslice to be cleared. -// \return void -// -// Clearing a arrayslice is equivalent to resetting it via the reset() function. -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time arrayslice arguments -inline void clear( ArraySlice& arrayslice ) -{ - arrayslice.reset(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Clearing the given temporary arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The temporary arrayslice to be cleared. -// \return void -// -// Clearing a arrayslice is equivalent to resetting it via the reset() function. -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time arrayslice arguments -inline void clear( ArraySlice&& arrayslice ) -{ - arrayslice.reset(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the given dense arrayslice is in default state. -// \ingroup arrayslice -// -// \param arrayslice The dense arrayslice to be tested for its default state. -// \return \a true in case the given dense arrayslice is component-wise zero, \a false otherwise. -// -// This function checks whether the dense arrayslice is in default state. For instance, in case the -// arrayslice is instantiated for a built-in integral or floating point data type, the function returns -// \a true in case all arrayslice elements are 0 and \a false in case any arrayslice element is not 0. The -// following example demonstrates the use of the \a isDefault function: - - \code - blaze::DynamicArray A; - // ... Resizing and initialization - if( isDefault( arrayslice( A, 0UL ) ) ) { ... } - \page() - -// Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed -// semantics (blaze::relaxed): - - \code - if( isDefault( arrayslice( A, 0UL ) ) ) { ... } - \page() -*/ -template< bool RF // Relaxation flag - , size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time arrayslice arguments -inline bool isDefault( const ArraySlice& arrayslice ) -{ - using blaze::isDefault; - - constexpr size_t N = ArraySlice::num_dimensions(); - - return ArrayForEachGroupedAllOf( - arrayslice.dimensions(), [&]( std::array< size_t, N > const& indices ) { - return isDefault( arrayslice( indices ) ); - } ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the invariants of the given arrayslice are intact. -// \ingroup arrayslice -// -// \param arrayslice The arrayslice to be tested. -// \return \a true in case the given arrayslice's invariants are intact, \a false otherwise. -// -// This function checks whether the invariants of the arrayslice are intact, i.e. if its state is valid. -// In case the invariants are intact, the function returns \a true, else it will return \a false. -// The following example demonstrates the use of the \a isIntact() function: - - \code - blaze::DynamicArray A; - // ... Resizing and initialization - if( isIntact( arrayslice( A, 0UL ) ) ) { ... } - \page() -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs > // Compile time arrayslice arguments -inline bool isIntact( const ArraySlice& arrayslice ) noexcept -{ - return ( arrayslice.index() < arrayslice.operand().template dimensions() && - isIntact( arrayslice.operand() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the two given arrayslices represent the same observable state. -// \ingroup arrayslice -// -// \param a The first arrayslice to be tested for its state. -// \param b The second arrayslice to be tested for its state. -// \return \a true in case the two arrayslices share a state, \a false otherwise. -// -// This overload of the isSame() function tests if the two given arrayslices refer to exactly the same -// range of the same array. In case both arrayslices represent the same observable state, the function -// returns \a true, otherwise it returns \a false. -*/ -template< size_t M1 // ArraySlice dimension - , typename MT1 // Type of the array of the left-hand side arrayslice - , size_t... CRAs1 // Compile time arrayslice arguments of the left-hand side arrayslice - , size_t M2 // ArraySlice dimension - , typename MT2 // Type of the array of the right-hand side arrayslice - , size_t... CRAs2 > // Compile time arrayslice arguments of the right-hand side arrayslice -inline bool isSame( const ArraySlice& a, - const ArraySlice& b ) noexcept -{ - return ( M1 == M2 && isSame( a.operand(), b.operand() ) && ( a.index() == b.index() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by setting a single element of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param i The row to be set. -// \param j The column to be set. -// \param value The value to be set to the element. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Number of dimensions - , typename ET > // Type of the element -inline bool trySet( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) -{ - constexpr size_t array_N = ( ~arrayslice.operand() ).num_dimensions(); - BLAZE_STATIC_ASSERT( N + 1 == array_N ); - - return trySet( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by adding to a single element of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param i The row to be modified. -// \param j The column to be modified. -// \param value The value to be added to the element. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename ET > // Type of the element -inline bool tryAdd( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) -{ - constexpr size_t array_N = ( ~arrayslice.operand() ).num_dimensions(); - BLAZE_STATIC_ASSERT( N + 1 == array_N ); - - return tryAdd( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by subtracting from a single element of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param i The row to be modified. -// \param j The column to be modified. -// \param value The value to be subtracted from the element. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename ET > // Type of the element -inline bool trySub( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) -{ - BLAZE_INTERNAL_ASSERT( i < arrayslice.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < arrayslice.columns(), "Invalid column access index" ); - - return trySub( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by scaling a single element of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param i The row to be modified. -// \param j The column to be modified. -// \param value The factor for the element. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename ET > // Type of the element -inline bool tryMult( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) -{ - BLAZE_INTERNAL_ASSERT( i < arrayslice.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < arrayslice.columns(), "Invalid column access index" ); - - return tryMult( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by scaling a range of elements of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param index The index of the first element of the range to be modified. -// \param size The number of elements of the range to be modified. -// \param value The factor for the elements. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename ET > // Type of the element -BLAZE_ALWAYS_INLINE bool - tryMult( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, std::array< size_t, N > const& sizes, const ET& value ) -{ - BLAZE_INTERNAL_ASSERT( row <= (~arrayslice).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( row + rows <= (~arrayslice).rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( col <= (~arrayslice).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( col + cols <= (~arrayslice).columns(), "Invalid columns range size" ); - - return tryMult( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), mergeDims( sizes, 1UL ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by scaling a single element of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param index The index of the element to be modified. -// \param value The divisor for the element. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename ET > // Type of the element -inline bool tryDiv( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, const ET& value ) -{ - BLAZE_INTERNAL_ASSERT( i < arrayslice.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( j < arrayslice.columns(), "Invalid column access index" ); - - return tryDiv( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by scaling a range of elements of a arrayslice. -// \ingroup arrayslice -// -// \param arrayslice The target arrayslice. -// \param index The index of the first element of the range to be modified. -// \param size The number of elements of the range to be modified. -// \param value The divisor for the elements. -// \return \a true in case the operation would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename ET > // Type of the element -BLAZE_ALWAYS_INLINE bool - tryDiv( const ArraySlice& arrayslice, std::array< size_t, N > const& dims, std::array< size_t, N > const& sizes, const ET& value ) -{ - BLAZE_INTERNAL_ASSERT( row <= (~arrayslice).rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( row + rows <= (~arrayslice).rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( col <= (~arrayslice).columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( col + cols <= (~arrayslice).columns(), "Invalid columns range size" ); - - return tryDiv( arrayslice.operand(), mergeDims( dims, arrayslice.index() ), mergeDims( sizes, 1UL ), value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by the assignment of a matrix to a arrayslice. -// \ingroup arrayslice -// -// \param lhs The target left-hand side arrayslice. -// \param rhs The right-hand side vector to be assigned. -// \param index The index of the first element to be modified. -// \return \a true in case the assignment would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename VT > // Type of the right-hand side matrix -inline bool tryAssign( const ArraySlice& lhs, - const Matrix& rhs, std::array< size_t, N > const& dims ) -{ - BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); - - return tryAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by the addition assignment of a vector to a arrayslice. -// \ingroup arrayslice -// -// \param lhs The target left-hand side arrayslice. -// \param rhs The right-hand side vector to be added. -// \param index The index of the first element to be modified. -// \return \a true in case the assignment would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename VT > // Type of the right-hand side matrix -inline bool tryAddAssign( const ArraySlice& lhs, - const Matrix& rhs, std::array< size_t, N > const& dims ) -{ - BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); - - return tryAddAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by the subtraction assignment of a vector to a arrayslice. -// \ingroup arrayslice -// -// \param lhs The target left-hand side arrayslice. -// \param rhs The right-hand side vector to be subtracted. -// \param index The index of the first element to be modified. -// \return \a true in case the assignment would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename VT > // Type of the right-hand side matrix -inline bool trySubAssign( const ArraySlice& lhs, - const Matrix& rhs, std::array< size_t, N > const& dims ) -{ - BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); - - return trySubAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by the multiplication assignment of a vector to a arrayslice. -// \ingroup arrayslice -// -// \param lhs The target left-hand side arrayslice. -// \param rhs The right-hand side vector to be multiplied. -// \param index The index of the first element to be modified. -// \return \a true in case the assignment would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename VT > // Type of the right-hand side matrix -inline bool tryMultAssign( const ArraySlice& lhs, - const Vector& rhs, std::array< size_t, N > const& dims ) -{ - BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); - - return tryMultAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Predict invariant violations by the division assignment of a vector to a arrayslice. -// \ingroup arrayslice -// -// \param lhs The target left-hand side arrayslice. -// \param rhs The right-hand side vector divisor. -// \param index The index of the first element to be modified. -// \return \a true in case the assignment would be successful, \a false if not. -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the array - , size_t... CRAs // Compile time arrayslice arguments - , size_t N // Dimensions of the ArraysSlice - , typename VT > // Type of the right-hand side matrix -inline bool tryDivAssign( const ArraySlice& lhs, - const Matrix& rhs, std::array< size_t, N > const& dims ) -{ - BLAZE_INTERNAL_ASSERT( i <= lhs.rows(), "Invalid row access index" ); - BLAZE_INTERNAL_ASSERT( i + (~rhs).rows() <= lhs.rows(), "Invalid rows range size" ); - BLAZE_INTERNAL_ASSERT( j <= lhs.columns(), "Invalid column access index" ); - BLAZE_INTERNAL_ASSERT( j + (~rhs).columns() <= lhs.columns(), "Invalid columns range size" ); - - return tryDivAssign( lhs.operand(), ~rhs, mergeDims( dims, arrayslice.index() ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Removal of all restrictions on the data access to the given arrayslice. -// \ingroup arrayslice -// -// \param r The arrayslice to be derestricted. -// \return ArraySlice without access restrictions. -// -// This function removes all restrictions on the data access to the given arrayslice. It returns a arrayslice -// object that does provide the same interface but does not have any restrictions on the data -// access.\n -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in the violation of invariants, erroneous results and/or in compilation errors. -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t I > // ArraySlice index -inline decltype(auto) derestrict( ArraySlice& r ) -{ - return arrayslice( derestrict( r.operand() ), unchecked ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Removal of all restrictions on the data access to the given temporary arrayslice. -// \ingroup arrayslice -// -// \param r The temporary arrayslice to be derestricted. -// \return ArraySlice without access restrictions. -// -// This function removes all restrictions on the data access to the given temporary arrayslice. It -// returns a arrayslice object that does provide the same interface but does not have any restrictions -// on the data access.\n -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in the violation of invariants, erroneous results and/or in compilation errors. -*/ -template< size_t M // ArraySlice dimension - , typename MT // Type of the array - , size_t I > // ArraySlice index -inline decltype(auto) derestrict( ArraySlice&& r ) -{ - return arrayslice( derestrict( r.operand() ), unchecked ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Removal of all restrictions on the data access to the given arrayslice. -// \ingroup arrayslice -// -// \param r The arrayslice to be derestricted. -// \return ArraySlice without access restrictions. -// -// This function removes all restrictions on the data access to the given arrayslice. It returns a arrayslice -// object that does provide the same interface but does not have any restrictions on the data -// access.\n -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in the violation of invariants, erroneous results and/or in compilation errors. -*/ -template< size_t M // ArraySlice dimension - , typename MT > // ArraySlice index -inline decltype(auto) derestrict( ArraySlice& r ) -{ - return arrayslice( derestrict( r.operand() ), r.index(), unchecked ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Removal of all restrictions on the data access to the given temporary arrayslice. -// \ingroup arrayslice -// -// \param r The temporary arrayslice to be derestricted. -// \return ArraySlice without access restrictions. -// -// This function removes all restrictions on the data access to the given temporary arrayslice. It -// returns a arrayslice object that does provide the same interface but does not have any restrictions -// on the data access.\n -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in the violation of invariants, erroneous results and/or in compilation errors. -*/ -template< size_t M // ArraySlice dimension - , typename MT > // ArraySlice index -inline decltype(auto) derestrict( ArraySlice&& r ) -{ - return arrayslice( derestrict( r.operand() ), r.index(), unchecked ); -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// SIZE SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs, size_t Index > -struct Size< ArraySlice< M, MT, CRAs... >, Index > - : public Size< MT, ( Index < M ) ? Index : Index + 1 > -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// MAXSIZE SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs, size_t Index > -struct MaxSize< ArraySlice< M, MT, CRAs... >, Index > - : public MaxSize< MT, ( Index < M ) ? Index : Index + 1 > -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ISRESTRICTED SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs > -struct IsRestricted< ArraySlice > - : public IsRestricted -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// HASCONSTDATAACCESS SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs > -struct HasConstDataAccess< ArraySlice > - : public HasConstDataAccess -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// HASMUTABLEDATAACCESS SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs > -struct HasMutableDataAccess< ArraySlice > - : public HasMutableDataAccess -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ISALIGNED SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs > -struct IsAligned< ArraySlice > - : public BoolConstant< IsAligned_v > -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ISCONTIGUOUS SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs > -struct IsContiguous< ArraySlice > - : public IsContiguous -{}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ISPADDED SPECIALIZATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -template< size_t M, typename MT, size_t... CRAs > -struct IsPadded< ArraySlice > - : public BoolConstant< IsPadded_v > -{}; -/*! \endcond */ -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/views/Forward.h b/blaze_tensor/math/views/Forward.h index f7d11a7..bf34c58 100644 --- a/blaze_tensor/math/views/Forward.h +++ b/blaze_tensor/math/views/Forward.h @@ -47,12 +47,12 @@ #include #include -#include #include #include #include #include #include +#include #include #include @@ -303,23 +303,24 @@ decltype(auto) rowslice( const Tensor&, size_t, RRAs... ); template< typename TT, typename... RRAs > decltype(auto) rowslice( Tensor&&, size_t, RRAs... ); -template< size_t M, size_t I, typename AT, typename... RRAs > -decltype(auto) arrayslice( Array&, RRAs... ); -template< size_t M, size_t I, typename AT, typename... RRAs > -decltype(auto) arrayslice( const Array&, RRAs... ); +template< size_t I, typename AT, typename... RRAs > +decltype(auto) quatslice( Array&, RRAs... ); -template< size_t M, size_t I, typename AT, typename... RRAs > -decltype(auto) arrayslice( Array&&, RRAs... ); +template< size_t I, typename AT, typename... RRAs > +decltype(auto) quatslice( const Array&, RRAs... ); -template< size_t M, typename AT, typename... RRAs > -decltype(auto) arrayslice( Array&, size_t, RRAs... ); +template< size_t I, typename AT, typename... RRAs > +decltype(auto) quatslice( Array&&, RRAs... ); -template< size_t M, typename AT, typename... RRAs > -decltype(auto) arrayslice( const Array&, size_t, RRAs... ); +template< typename AT, typename... RRAs > +decltype(auto) quatslice( Array&, size_t, RRAs... ); -template< size_t M, typename AT, typename... RRAs > -decltype(auto) arrayslice( Array&&, size_t, RRAs... ); +template< typename AT, typename... RRAs > +decltype(auto) quatslice( const Array&, size_t, RRAs... ); + +template< typename AT, typename... RRAs > +decltype(auto) quatslice( Array&&, size_t, RRAs... ); // template< size_t I, size_t... Is, typename TT, typename... RCAs > // decltype(auto) pages( Tensor&, RCAs... ); diff --git a/blaze_tensor/math/views/QuatSlice.h b/blaze_tensor/math/views/QuatSlice.h index f863d6f..69645a7 100644 --- a/blaze_tensor/math/views/QuatSlice.h +++ b/blaze_tensor/math/views/QuatSlice.h @@ -49,7 +49,7 @@ //#include //#include #include -#include +//#include #include #include //#include @@ -905,7 +905,7 @@ inline bool isDefault( const QuatSlice& quatslice ) { using blaze::isDefault; - for( size_t k=0UL; k<(~sm).pages(); ++k ) + for( size_t k=0UL; k( quatslice(k, i, j) ) ) diff --git a/blaze_tensor/math/views/Subtensor.h b/blaze_tensor/math/views/Subtensor.h index 12a399c..28cc224 100644 --- a/blaze_tensor/math/views/Subtensor.h +++ b/blaze_tensor/math/views/Subtensor.h @@ -1757,8 +1757,6 @@ inline decltype(auto) { BLAZE_FUNCTION_TRACE; - using TT = RemoveReference_t< LeftOperand_t< MatrixType_t > >; - const SubmatrixData sm( args... ); BLAZE_DECLTYPE_AUTO( left , (~matrix).leftOperand() ); diff --git a/blaze_tensor/math/views/arrayslice/ArraySlice.h b/blaze_tensor/math/views/arrayslice/ArraySlice.h deleted file mode 100644 index 6a55cbc..0000000 --- a/blaze_tensor/math/views/arrayslice/ArraySlice.h +++ /dev/null @@ -1,328 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_tensor/math/views/arrayslice/PageSlice.h -// \brief PageSlice documentation -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICE_H_ -#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICE_H_ - - -//================================================================================================= -// -// DOXYGEN DOCUMENTATION -// -//================================================================================================= - -//************************************************************************************************* -/*!\defgroup arrayslice PageSlice -// \ingroup views -// -// PageSlices provide views on a specific arrayslice of a dense or sparse tensor. As such, arrayslices act as a -// reference to a specific arrayslice. This reference is valid and can be used in every way any other -// arrayslice matrix can be used as long as the tensor containing the arrayslice is not resized or entirely -// destroyed. The arrayslice also acts as an alias to the arrayslice elements: Changes made to the elements -// (e.g. modifying values, inserting or erasing elements) are immediately visible in the tensor -// and changes made via the tensor are immediately visible in the arrayslice. -// -// -// \n \section arrayslice_setup Setup of PageSlices -// -// \image html arrayslice.png -// \image latex arrayslice.eps "PageSlice view" width=250pt -// -// A reference to a dense or sparse arrayslice can be created very conveniently via the \c arrayslice() function. -// It can be included via the header file - - \code - #include - \endcode - -// The arrayslice index must be in the range from \f$[0..M-1]\f$, where \c M is the total number of arrayslices -// of the tensor, and can be specified both at compile time or at runtime: - - \code - blaze::DynamicTensor A; - // ... Resizing and initialization - - // Creating a reference to the 1st arrayslice of tensor A (compile time index) - auto arrayslice1 = arrayslice<1UL>( A ); - - // Creating a reference to the 2nd arrayslice of tensor A (runtime index) - auto arrayslice2 = arrayslice( A, 2UL ); - \endcode - -// The \c arrayslice() function returns an expression representing the arrayslice view. The type of this -// expression depends on the given arrayslice arguments, primarily the type of the tensor and the compile -// time arguments. If the type is required, it can be determined via \c decltype specifier: - - \code - using TensorType = blaze::DynamicTensor; - using PageSliceType = decltype( blaze::arrayslice<1UL>( std::declval() ) ); - \endcode - -// The resulting view can be treated as any other arrayslice matrix, i.e. it can be assigned to, it can -// be copied from, and it can be used in arithmetic operations. The reference can also be used on -// both sides of an assignment: The arrayslice can either be used as an alias to grant write access to a -// specific arrayslice of a tensor primitive on the left-hand side of an assignment or to grant read-access -// to a specific arrayslice of a tensor primitive or expression on the right-hand side of an assignment. -// The following example demonstrates this in detail: - - \code - blaze::DynamicMatrix x; - blaze::DynamicTensor A, B; - // ... Resizing and initialization - - // Setting the 2nd arrayslice of tensor A to x - auto arrayslice2 = arrayslice( A, 2UL ); - arrayslice2 = x; - - // Setting the 3rd arrayslice of tensor B to x - arrayslice( B, 3UL ) = x; - - // Setting x to the 4th arrayslice of the result of the tensor multiplication - x = arrayslice( A * B, 4UL ); - \endcode - -// \n \section arrayslice_element_access Element access -// -// The elements of a arrayslice can be directly accessed with the subscript operator: - - \code - blaze::DynamicTensor A; - // ... Resizing and initialization - - // Creating a view on the 4th arrayslice of tensor A - auto arrayslice4 = arrayslice( A, 4UL ); - - // Setting the 1st element of the dense arrayslice, which corresponds - // to the 1st element in the 4th arrayslice of tensor A - arrayslice4(0, 0) = 2.0; - \endcode - -// The numbering of the arrayslice elements is - - \f[\left(\begin{array}{*{5}{c}} - 0 & 1 & 2 & \cdots & N-1 \\ - \end{array}\right),\f] - -// where N is the number of columns of the referenced tensor. Alternatively, the elements of a -// arrayslice can be traversed via iterators. Just as with vectors, in case of non-const arrayslices, \c begin() -// and \c end() return an iterator, which allows to manipulate the elements, in case of constant -// arrayslices an iterator to immutable elements is returned: - - \code - blaze::DynamicTensor A( 128UL, 256UL ); - // ... Resizing and initialization - - // Creating a reference to the 31st arrayslice of tensor A - auto arrayslice31 = arrayslice( A, 31UL ); - - // Traversing the elements via iterators to non-const elements - for( auto it=arrayslice31.begin(); it!=arrayslice31.end(); ++it ) { - *it = ...; // OK; Write access to the dense arrayslice value - ... = *it; // OK: Read access to the dense arrayslice value. - } - - // Traversing the elements via iterators to const elements - for( auto it=arrayslice31.cbegin(); it!=arrayslice31.cend(); ++it ) { - *it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. - ... = *it; // OK: Read access to the dense arrayslice value. - } - \endcode - - \code - blaze::CompressedMatrix A( 128UL, 256UL ); - // ... Resizing and initialization - - // Creating a reference to the 31st arrayslice of tensor A - auto arrayslice31 = arrayslice( A, 31UL ); - - // Traversing the elements via iterators to non-const elements - for( auto it=arrayslice31.begin(); it!=arrayslice31.end(); ++it ) { - it->value() = ...; // OK: Write access to the value of the non-zero element. - ... = it->value(); // OK: Read access to the value of the non-zero element. - it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. - ... = it->index(); // OK: Read access to the index of the sparse element. - } - - // Traversing the elements via iterators to const elements - for( auto it=arrayslice31.cbegin(); it!=arrayslice31.cend(); ++it ) { - it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid. - ... = it->value(); // OK: Read access to the value of the non-zero element. - it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed. - ... = it->index(); // OK: Read access to the index of the sparse element. - } - \endcode - -// \n \section sparse_arrayslice_element_insertion Element Insertion -// -// Inserting/accessing elements in a sparse arrayslice can be done by several alternative functions. -// The following example demonstrates all options: - - \code - blaze::CompressedMatrix A( 10UL, 100UL ); // Non-initialized 10x100 tensor - - auto arrayslice0( arrayslice( A, 0UL ) ); // Reference to the 0th arrayslice of A - - // The subscript operator provides access to all possible elements of the sparse arrayslice, - // including the zero elements. In case the subscript operator is used to access an element - // that is currently not stored in the sparse arrayslice, the element is inserted into the arrayslice. - arrayslice0[42] = 2.0; - - // The second operation for inserting elements is the set() function. In case the element - // is not contained in the arrayslice it is inserted into the arrayslice, if it is already contained in - // the arrayslice its value is modified. - arrayslice0.set( 45UL, -1.2 ); - - // An alternative for inserting elements into the arrayslice is the insert() function. However, - // it inserts the element only in case the element is not already contained in the arrayslice. - arrayslice0.insert( 50UL, 3.7 ); - - // A very efficient way to add new elements to a sparse arrayslice is the append() function. - // Note that append() requires that the appended element's index is strictly larger than - // the currently largest non-zero index of the arrayslice and that the arrayslice's capacity is large - // enough to hold the new element. - arrayslice0.reserve( 10UL ); - arrayslice0.append( 51UL, -2.1 ); - \endcode - -// \n \section arrayslice_common_operations Common Operations -// -// A arrayslice view can be used like any other arrayslice vector. For instance, the current number of arrayslice -// elements can be obtained via the \c size() function, the current capacity via the \c capacity() -// function, and the number of non-zero elements via the \c nonZeros() function. However, since -// arrayslices are references to specific arrayslices of a tensor, several operations are not possible, such as -// resizing and swapping. The following example shows this by means of a dense arrayslice view: - - \code - blaze::DynamicTensor A( 42UL, 42UL ); - // ... Resizing and initialization - - // Creating a reference to the 2nd arrayslice of tensor A - auto arrayslice2 = arrayslice( A, 2UL ); - - arrayslice2.size(); // Returns the number of elements in the arrayslice - arrayslice2.capacity(); // Returns the capacity of the arrayslice - arrayslice2.nonZeros(); // Returns the number of non-zero elements contained in the arrayslice - - arrayslice2.resize( 84UL ); // Compilation error: Cannot resize a single arrayslice of a tensor - - auto arrayslice3 = arrayslice( A, 3UL ); - swap( arrayslice2, arrayslice3 ); // Compilation error: Swap operation not allowed - \endcode - -// \n \section arrayslice_arithmetic_operations Arithmetic Operations -// -// Both dense and sparse arrayslices can be used in all arithmetic operations that any other dense or -// sparse arrayslice vector can be used in. The following example gives an impression of the use of -// dense arrayslices within arithmetic operations. All operations (addition, subtraction, multiplication, -// scaling, ...) can be performed on all possible combinations of dense and sparse arrayslices with -// fitting element types: - - \code - blaze::DynamicVector a( 2UL, 2.0 ), b; - blaze::CompressedVector c( 2UL ); - c[1] = 3.0; - - blaze::DynamicTensor A( 4UL, 2UL ); // Non-initialized 4x2 tensor - - auto arrayslice0( arrayslice( A, 0UL ) ); // Reference to the 0th arrayslice of A - - arrayslice0[0] = 0.0; // Manual initialization of the 0th arrayslice of A - arrayslice0[1] = 0.0; - arrayslice( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st arrayslice of A - arrayslice( A, 2UL ) = a; // Dense vector initialization of the 2nd arrayslice of A - arrayslice( A, 3UL ) = c; // Sparse vector initialization of the 3rd arrayslice of A - - b = arrayslice0 + a; // Dense vector/dense vector addition - b = c + arrayslice( A, 1UL ); // Sparse vector/dense vector addition - b = arrayslice0 * arrayslice( A, 2UL ); // Component-wise vector multiplication - - arrayslice( A, 1UL ) *= 2.0; // In-place scaling of the 1st arrayslice - b = arrayslice( A, 1UL ) * 2.0; // Scaling of the 1st arrayslice - b = 2.0 * arrayslice( A, 1UL ); // Scaling of the 1st arrayslice - - arrayslice( A, 2UL ) += a; // Addition assignment - arrayslice( A, 2UL ) -= c; // Subtraction assignment - arrayslice( A, 2UL ) *= arrayslice( A, 0UL ); // Multiplication assignment - - double scalar = arrayslice( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors - - A = trans( c ) * arrayslice( A, 1UL ); // Outer product between two vectors - \endcode - -// \n \section arrayslice_on_column_major_tensor PageSlices on Column-Major Matrices -// -// Especially noteworthy is that arrayslice views can be created for both arrayslice-major and column-major -// matrices. Whereas the interface of a arrayslice-major tensor only allows to traverse a arrayslice directly -// and the interface of a column-major tensor only allows to traverse a column, via views it is -// possible to traverse a arrayslice of a column-major tensor or a column of a arrayslice-major tensor. For -// instance: - - \code - blaze::DynamicTensor A( 64UL, 32UL ); - // ... Resizing and initialization - - // Creating a reference to the 1st arrayslice of a column-major tensor A - auto arrayslice1 = arrayslice( A, 1UL ); - - for( auto it=arrayslice1.begin(); it!=arrayslice1.end(); ++it ) { - // ... - } - \endcode - -// However, please note that creating a arrayslice view on a tensor stored in a column-major fashion -// can result in a considerable performance decrease in comparison to a arrayslice view on a tensor -// with arrayslice-major storage format. This is due to the non-contiguous storage of the tensor -// elements. Therefore care has to be taken in the choice of the most suitable storage order: - - \code - // Setup of two column-major matrices - blaze::DynamicTensor A( 128UL, 128UL ); - blaze::DynamicTensor B( 128UL, 128UL ); - // ... Resizing and initialization - - // The computation of the 15th arrayslice of the multiplication between A and B ... - blaze::DynamicVector x = arrayslice( A * B, 15UL ); - - // ... is essentially the same as the following computation, which multiplies - // the 15th arrayslice of the column-major tensor A with B. - blaze::DynamicVector x = arrayslice( A, 15UL ) * B; - \endcode - -// Although Blaze performs the resulting vector/tensor multiplication as efficiently as possible -// using a arrayslice-major storage order for tensor \c A would result in a more efficient evaluation. -*/ -//************************************************************************************************* - -#endif diff --git a/blaze_tensor/math/views/arrayslice/ArraySliceData.h b/blaze_tensor/math/views/arrayslice/ArraySliceData.h deleted file mode 100644 index 5d6ad16..0000000 --- a/blaze_tensor/math/views/arrayslice/ArraySliceData.h +++ /dev/null @@ -1,251 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_tensor/math/views/arrayslice/ArraySliceData.h -// \brief Header file for the implementation of the ArraySliceData class template -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICEDATA_H_ -#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_ARRAYSLICEDATA_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include - - -namespace blaze { - -//================================================================================================= -// -// CLASS DEFINITION -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Auxiliary class template for the data members of the ArraySlice class. -// \ingroup arrayslice -// -// The auxiliary ArraySliceData class template represents an abstraction of the data members of the -// ArraySlice class template. The necessary set of data members is selected depending on the number -// of compile time arrayslice arguments. -*/ -template< size_t... CRAs > // Compile time arrayslice arguments -struct ArraySliceData -{}; -//************************************************************************************************* - - - - -//================================================================================================= -// -// CLASS TEMPLATE SPECIALIZATION FOR ZERO COMPILE TIME PAGESLICE INDICES -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the ArraySliceData class template for zero compile time arrayslice arguments. -// \ingroup arrayslice -// -// This specialization of ArraySliceData adapts the class template to the requirements of zero compile -// time arrayslice arguments. -*/ -template<> -struct ArraySliceData<> -{ - public: - //**Constructors******************************************************************************** - /*!\name Constructors */ - //@{ - template< typename... RRAs > - explicit inline ArraySliceData( size_t index, RRAs... args ); - - ArraySliceData( const ArraySliceData& ) = default; - //@} - //********************************************************************************************** - - //**Destructor********************************************************************************** - /*!\name Destructor */ - //@{ - ~ArraySliceData() = default; - //@} - //********************************************************************************************** - - //**Assignment operators************************************************************************ - /*!\name Assignment operators */ - //@{ - ArraySliceData& operator=( const ArraySliceData& ) = delete; - //@} - //********************************************************************************************** - - //**Utility functions*************************************************************************** - /*!\name Utility functions */ - //@{ - inline size_t index() const noexcept; - //@} - //********************************************************************************************** - - private: - //**Member variables**************************************************************************** - /*!\name Member variables */ - //@{ - const size_t arrayslice_; //!< The index of the arrayslice in the tensor. - //@} - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief The constructor for ArraySliceData. -// -// \param index The index of the arrayslice. -// \param args The optional arrayslice arguments. -*/ -template< typename... RRAs > // Optional arrayslice arguments -inline ArraySliceData<>::ArraySliceData( size_t index, RRAs... args ) - : arrayslice_( index ) // The index of the arrayslice in the tensor -{ - MAYBE_UNUSED( args... ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the index of the arrayslice of the underlying dense tensor. -// -// \return The index of the arrayslice. -*/ -inline size_t ArraySliceData<>::index() const noexcept -{ - return arrayslice_; -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// CLASS TEMPLATE SPECIALIZATION FOR ONE COMPILE TIME PAGESLICE INDEX -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of the ArraySliceData class template for a single compile time arrayslice argument. -// \ingroup arrayslice -// -// This specialization of ArraySliceData adapts the class template to the requirements of a single -// compile time arrayslice argument. -*/ -template< size_t Index > // Compile time arrayslice index -struct ArraySliceData -{ - public: - //**Constructors******************************************************************************** - /*!\name Constructors */ - //@{ - template< typename... RRAs > - explicit inline ArraySliceData( RRAs... args ); - - ArraySliceData( const ArraySliceData& ) = default; - //@} - //********************************************************************************************** - - //**Destructor********************************************************************************** - /*!\name Destructor */ - //@{ - ~ArraySliceData() = default; - //@} - //********************************************************************************************** - - //**Assignment operators************************************************************************ - /*!\name Assignment operators */ - //@{ - ArraySliceData& operator=( const ArraySliceData& ) = delete; - //@} - //********************************************************************************************** - - //**Utility functions*************************************************************************** - /*!\name Utility functions */ - //@{ - static inline constexpr size_t index() noexcept; - //@} - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief The constructor for ArraySliceData. -// -// \param args The optional arrayslice arguments. -*/ -template< size_t Index > // Compile time arrayslice index -template< typename... RRAs > // Optional arrayslice arguments -inline ArraySliceData::ArraySliceData( RRAs... args ) -{ - MAYBE_UNUSED( args... ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the index of the arrayslice of the underlying dense tensor. -// -// \return The index of the arrayslice. -*/ -template< size_t Index > // Compile time arrayslice index -inline constexpr size_t ArraySliceData::index() noexcept -{ - return Index; -} -/*! \endcond */ -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/views/arrayslice/BaseTemplate.h b/blaze_tensor/math/views/arrayslice/BaseTemplate.h deleted file mode 100644 index 6769c64..0000000 --- a/blaze_tensor/math/views/arrayslice/BaseTemplate.h +++ /dev/null @@ -1,123 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_tensor/math/views/arrayslice/BaseTemplate.h -// \brief Header file for the implementation of the ArraySlice base template -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_BASETEMPLATE_H_ -#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_BASETEMPLATE_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// #include -// #include -#include -// #include -// #include -#include -#include -// #include -// #include -#include - - -namespace blaze { - -//================================================================================================= -// -// ::blaze NAMESPACE FORWARD DECLARATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Base template of the ArraySlice class template. -// \ingroup arrayslice -*/ -template< size_t M // Dimension of the slice - , typename MT // Type of the tensor - , size_t... CRAs > // Compile time arrayslice arguments -class ArraySlice; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ALIAS DECLARATIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Auxiliary alias declaration for the ArraySlice class template. -// \ingroup arrayslice -// -// The ArraySlice_ alias declaration represents a convenient shortcut for the specification of the -// non-derived template arguments of the ArraySlice class template. -*/ -template< size_t M // Dimension of the slice - , typename MT // Type of the tensor - , size_t... CRAs > // Compile time arrayslice arguments -using ArraySlice_ = ArraySlice< M, MT, CRAs... >; -/*! \endcond */ -//************************************************************************************************* - -} // namespace blaze - -#endif diff --git a/blaze_tensor/math/views/arrayslice/Dense.h b/blaze_tensor/math/views/arrayslice/Dense.h deleted file mode 100644 index 0ca643b..0000000 --- a/blaze_tensor/math/views/arrayslice/Dense.h +++ /dev/null @@ -1,2321 +0,0 @@ -//================================================================================================= -/*! -// \file blaze_array/math/views/arrayslice/Dense.h -// \brief ArraySlice specialization for dense arrays -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_DENSE_H_ -#define _BLAZE_TENSOR_MATH_VIEWS_ARRAYSLICE_DENSE_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -// #include -#include -#include -#include - - -namespace blaze { - -//================================================================================================= -// -// CLASS TEMPLATE SPECIALIZATION FOR DENSE TENSORS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Specialization of ArraySlice for arrayslices on arrayslice-major dense arrays. -// \ingroup arrayslice -// -// This specialization of ArraySlice adapts the class template to the requirements of arrayslice-major -// dense arrays. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -class ArraySlice - : public View< DenseArray< ArraySlice > > - , private ArraySliceData -{ - private: - //**Type definitions**************************************************************************** - using DataType = ArraySliceData; //!< The type of the ArraySliceData base class. - using Operand = If_t< IsExpression_v, MT, MT& >; //!< Composite data type of the dense array expression. - //********************************************************************************************** - - public: - //**Type definitions**************************************************************************** - //! Type of this ArraySlice instance. - using This = ArraySlice; - - using BaseType = DenseArray; //!< Base type of this ArraySlice instance. - using ViewedType = MT; //!< The type viewed by this ArraySlice instance. - using ResultType = ArraySliceTrait_t; //!< Result type for expression template evaluations. - using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. - using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. - using ElementType = ElementType_t; //!< Type of the arrayslice elements. - using SIMDType = SIMDTrait_t; //!< SIMD type of the arrayslice elements. - using ReturnType = ReturnType_t; //!< Return type for expression template evaluations - using CompositeType = const ArraySlice&; //!< Data type for composite expression templates. - - //! Reference to a constant arrayslice value. - using ConstReference = ConstReference_t; - - //! Reference to a non-constant arrayslice value. - using Reference = If_t< IsConst_v, ConstReference, Reference_t >; - - //! Pointer to a constant arrayslice value. - using ConstPointer = ConstPointer_t; - - //! Pointer to a non-constant arrayslice value. - using Pointer = If_t< IsConst_v || !HasMutableDataAccess_v, ConstPointer, Pointer_t >; - - //! Iterator over constant elements. - using ConstIterator = ConstIterator_t; - - //! Iterator over non-constant elements. - using Iterator = If_t< IsConst_v, ConstIterator, Iterator_t >; - //********************************************************************************************** - - //**Compilation flags*************************************************************************** - //! Compilation switch for the expression template evaluation strategy. - static constexpr bool simdEnabled = MT::simdEnabled; - - //! Compilation switch for the expression template assignment strategy. - static constexpr bool smpAssignable = MT::smpAssignable; - - //! Compile time dimensions of this array slice. - static constexpr size_t N = MT::num_dimensions() - 1; - //********************************************************************************************** - - //**Constructors******************************************************************************** - /*!\name Constructors */ - //@{ - template< typename... RRAs > - explicit inline ArraySlice( MT& array, RRAs... args ); - - ArraySlice( const ArraySlice& ) = default; - //@} - //********************************************************************************************** - - //**Destructor********************************************************************************** - /*!\name Destructor */ - //@{ - ~ArraySlice() = default; - //@} - //********************************************************************************************** - - //**Data access functions*********************************************************************** - /*!\name Data access functions */ - //@{ - template< typename... Dims > - inline Reference operator()( Dims... dims ); - template< typename... Dims > - inline ConstReference operator()( Dims... dims ) const; - inline Reference operator()( std::array< size_t, N > const& indices ); - inline ConstReference operator()( std::array< size_t, N > const& indices ) const; - template< typename... Dims > - inline Reference at( Dims... dims ); - template< typename... Dims > - inline ConstReference at( Dims... dims ) const; - inline Pointer data () noexcept; - inline ConstPointer data () const noexcept; - inline Pointer data ( size_t i ) noexcept; - inline ConstPointer data ( size_t i ) const noexcept; - inline Iterator begin ( size_t i ); - inline ConstIterator begin ( size_t i ) const; - inline ConstIterator cbegin( size_t i ) const; - inline Iterator end ( size_t i ); - inline ConstIterator end ( size_t i ) const; - inline ConstIterator cend ( size_t i ) const; - //@} - //********************************************************************************************** - - //**Assignment operators************************************************************************ - /*!\name Assignment operators */ - //@{ - inline ArraySlice& operator=( const ElementType& rhs ); - inline ArraySlice& operator=( nested_initializer_list list ); - inline ArraySlice& operator=( const ArraySlice& rhs ); - - template< typename MT2 > inline ArraySlice& operator= ( const Array& rhs ); - template< typename MT2 > inline ArraySlice& operator+=( const Array& rhs ); - template< typename MT2 > inline ArraySlice& operator-=( const Array& rhs ); - template< typename MT2 > inline ArraySlice& operator%=( const Array& rhs ); - - template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > - inline ArraySlice& operator= ( const Vector& m ); - template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > - inline ArraySlice& operator+=( const Vector& m ); - template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > - inline ArraySlice& operator-=( const Vector& m ); - template< typename MT, bool TF, size_t M2 = N, typename = EnableIf_t< M2 == 1 > > - inline ArraySlice& operator%=( const Vector& m ); - - template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > - inline ArraySlice& operator= ( const Matrix& m ); - template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > - inline ArraySlice& operator+=( const Matrix& m ); - template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > - inline ArraySlice& operator-=( const Matrix& m ); - template< typename MT, bool SO, size_t M2 = N, typename = EnableIf_t< M2 == 2 > > - inline ArraySlice& operator%=( const Matrix& m ); - - template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > - inline ArraySlice& operator= ( const Tensor& m ); - template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > - inline ArraySlice& operator+=( const Tensor& m ); - template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > - inline ArraySlice& operator-=( const Tensor& m ); - template< typename MT, size_t M2 = N, typename = EnableIf_t< M2 == 3 > > - inline ArraySlice& operator%=( const Tensor& m ); - //@} - //********************************************************************************************** - - //**Utility functions*************************************************************************** - /*!\name Utility functions */ - //@{ - using DataType::index; - - inline MT& operand() noexcept; - inline const MT& operand() const noexcept; - - inline size_t rows() const noexcept; - inline size_t columns() const noexcept; - inline size_t spacing() const noexcept; - inline size_t capacity() const noexcept; - inline size_t capacity( size_t i ) const noexcept; - inline size_t nonZeros() const; - inline size_t nonZeros( size_t i ) const; - inline void reset(); - inline void reset( size_t i ); - //@} - //********************************************************************************************** - - //**Numeric functions*************************************************************************** - /*!\name Numeric functions */ - //@{ - template< typename Other > inline ArraySlice& scale( const Other& scalar ); - //@} - //********************************************************************************************** - - private: - //********************************************************************************************** - //! Helper variable template for the explicit application of the SFINAE principle. - template< typename MT2 > - static constexpr bool VectorizedAssign_v = - ( useOptimizedKernels && - simdEnabled && MT2::simdEnabled && - IsSIMDCombinable_v< ElementType, ElementType_t > ); - //********************************************************************************************** - - //********************************************************************************************** - //! Helper variable template for the explicit application of the SFINAE principle. - template< typename MT2 > - static constexpr bool VectorizedAddAssign_v = - ( useOptimizedKernels && - simdEnabled && MT2::simdEnabled && - IsSIMDCombinable_v< ElementType, ElementType_t > && - HasSIMDAdd_v< ElementType, ElementType_t > ); - //********************************************************************************************** - - //********************************************************************************************** - //! Helper variable template for the explicit application of the SFINAE principle. - template< typename MT2 > - static constexpr bool VectorizedSubAssign_v = - ( useOptimizedKernels && - simdEnabled && MT2::simdEnabled && - IsSIMDCombinable_v< ElementType, ElementType_t > && - HasSIMDSub_v< ElementType, ElementType_t > ); - //********************************************************************************************** - - //********************************************************************************************** - //! Helper variable template for the explicit application of the SFINAE principle. - template< typename MT2 > - static constexpr bool VectorizedSchurAssign_v = - ( useOptimizedKernels && - simdEnabled && MT2::simdEnabled && - IsSIMDCombinable_v< ElementType, ElementType_t > && - HasSIMDMult_v< ElementType, ElementType_t > ); - //********************************************************************************************** - - //**SIMD properties***************************************************************************** - //! The number of elements packed within a single SIMD element. - static constexpr size_t SIMDSIZE = SIMDTrait::size; - //********************************************************************************************** - - public: - //**Expression template evaluation functions**************************************************** - /*!\name Expression template evaluation functions */ - //@{ - template< typename Other > - inline bool canAlias( const Other* alias ) const noexcept; - - template< size_t M2, typename MT2, size_t... CRAs2 > - inline bool canAlias( const ArraySlice* alias ) const noexcept; - - template< typename Other > - inline bool isAliased( const Other* alias ) const noexcept; - - template< size_t M2, typename MT2, size_t... CRAs2 > - inline bool isAliased( const ArraySlice* alias ) const noexcept; - - inline bool isAligned () const noexcept; - inline bool canSMPAssign() const noexcept; - - template< typename... Dims > - BLAZE_ALWAYS_INLINE SIMDType load ( Dims... dims ) const noexcept; - template< typename... Dims > - BLAZE_ALWAYS_INLINE SIMDType loada( Dims... dims ) const noexcept; - template< typename... Dims > - BLAZE_ALWAYS_INLINE SIMDType loadu( Dims... dims ) const noexcept; - - template< typename... Dims > - BLAZE_ALWAYS_INLINE void store ( const SIMDType& value, Dims... dims ) noexcept; - template< typename... Dims > - BLAZE_ALWAYS_INLINE void storea( const SIMDType& value, Dims... dims ) noexcept; - template< typename... Dims > - BLAZE_ALWAYS_INLINE void storeu( const SIMDType& value, Dims... dims ) noexcept; - template< typename... Dims > - BLAZE_ALWAYS_INLINE void stream( const SIMDType& value, Dims... dims ) noexcept; - - template< typename MT2 > - inline auto assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v >; - - template< typename MT2 > - inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; - - template< typename MT2 > - inline auto addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; - - template< typename MT2 > - inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; - - template< typename MT2 > - inline auto subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; - - template< typename MT2 > - inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; - - template< typename MT2 > - inline auto schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; - - template< typename MT2 > - inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; - //@} - //********************************************************************************************** - - private: - //**Member variables**************************************************************************** - /*!\name Member variables */ - //@{ - Operand array_; //!< The array containing the arrayslice. - //@} - //********************************************************************************************** - - //**Friend declarations************************************************************************* - template< size_t M2, typename MT2, size_t... CRAs2 > friend class ArraySlice; - //********************************************************************************************** - - //**Compile time checks************************************************************************* - BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( MT ); - BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT ); - BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE ( MT ); -// BLAZE_CONSTRAINT_MUST_NOT_BE_SUBARRAY_TYPE ( MT ); - BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT ); - BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT ); - //********************************************************************************************** -}; -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// CONSTRUCTORS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Constructor for arrayslices on arrayslice-major dense arrays. -// -// \param array The array containing the arrayslice. -// \param args The runtime arrayslice arguments. -// \exception std::invalid_argument Invalid arrayslice access index. -// -// By default, the provided arrayslice arguments are checked at runtime. In case the arrayslice is not properly -// specified (i.e. if the specified index is greater than the number of pages of the given array) -// a \a std::invalid_argument exception is thrown. The checks can be skipped by providing the -// optional \a blaze::unchecked argument. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... RRAs > // Runtime arrayslice arguments -inline ArraySlice::ArraySlice( MT& array, RRAs... args ) - : DataType( args... ) // Base class initialization - , array_ ( array ) // The array containing the arrayslice -{ - if( !Contains_v< TypeList, Unchecked > ) { - if( array_.template dimension() <= index() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid arrayslice access index" ); - } - } - else { - BLAZE_USER_ASSERT( index() < array_..template dimension(), "Invalid arrayslice access index" ); - } -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// DATA ACCESS FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Subscript operator for the direct access to the arrayslice elements. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return Reference to the accessed value. -// -// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, -// the at() function is guaranteed to perform a check of the given access index. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -inline typename ArraySlice::Reference - ArraySlice::operator()( Dims... dims ) -{ - BLAZE_STATIC_ASSERT( M < sizeof...(Dims) ); - - return array_( fused_indices< M >( index(), dims... ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Subscript operator for the direct access to the arrayslice elements. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return Reference to the accessed value. -// -// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, -// the at() function is guaranteed to perform a check of the given access index. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -inline typename ArraySlice::ConstReference - ArraySlice::operator()( Dims... dims ) const -{ - BLAZE_STATIC_ASSERT( M < sizeof...(Dims) ); - - return const_cast< const MT& >( array_ )( fused_indices< M >( index(), dims... ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Subscript operator for the direct access to the arrayslice elements. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return Reference to the accessed value. -// -// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, -// the at() function is guaranteed to perform a check of the given access index. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::Reference - ArraySlice::operator()( std::array< size_t, N > const& indices ) -{ - BLAZE_STATIC_ASSERT( M < N ); - - return array_( fused_indices< M >( index(), indices ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Subscript operator for the direct access to the arrayslice elements. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return Reference to the accessed value. -// -// This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast, -// the at() function is guaranteed to perform a check of the given access index. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstReference - ArraySlice::operator()( std::array< size_t, N > const& indices ) const -{ - BLAZE_STATIC_ASSERT( M < N ); - - return const_cast< const MT& >( array_ )( fused_indices< M >( index(), indices ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Checked access to the arrayslice elements. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return Reference to the accessed value. -// \exception std::out_of_range Invalid arrayslice access index. -// -// In contrast to the subscript operator this function always performs a check of the given -// access index. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -inline typename ArraySlice::Reference - ArraySlice::at( Dims... dims ) -{ - size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dimensions(), [&]( size_t i, size_t dim ) { - if( indices[N - i - 1] >= dim ) { - BLAZE_THROW_OUT_OF_RANGE("Invalid array access index"); - } - } ); - - return ( *this )( dims... ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Checked access to the arrayslice elements. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return Reference to the accessed value. -// \exception std::out_of_range Invalid arrayslice access index. -// -// In contrast to the subscript operator this function always performs a check of the given -// access index. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -inline typename ArraySlice::ConstReference - ArraySlice::at( Dims... dims) const -{ - size_t indices[] = { size_t(dims)... }; - ArrayDimForEach( dimensions(), [&]( size_t i, size_t dim ) { - if( indices[N - i - 1] >= dim ) { - BLAZE_THROW_OUT_OF_RANGE("Invalid array access index"); - } - } ); - - return ( *this )( dims... ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Low-level data access to the arrayslice elements. -// -// \return Pointer to the internal element storage. -// -// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case -// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::Pointer - ArraySlice::data() noexcept -{ - return nullptr; //array_.data( fused_indices( index(), 0, 0 ) ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Low-level data access to the arrayslice elements. -// -// \return Pointer to the internal element storage. -// -// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case -// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstPointer - ArraySlice::data() const noexcept -{ - return nullptr; //array_.data( 0, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Low-level data access to the arrayslice elements. -// -// \return Pointer to the internal element storage. -// -// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case -// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::Pointer - ArraySlice::data( size_t i ) noexcept -{ - return nullptr; // array_.data( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Low-level data access to the arrayslice elements. -// -// \return Pointer to the internal element storage. -// -// This function returns a pointer to the internal storage of the dense arrayslice. Note that in case -// of a column-major array you can NOT assume that the arrayslice elements lie adjacent to each other! -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstPointer - ArraySlice::data( size_t i ) const noexcept -{ - return nullptr; // array_.data( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns an iterator to the first element of the arrayslice. -// -// \param i The row/column index. -// \return Iterator to the first element of the given row on this arrayslice. -// -// This function returns an iterator to the first element of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::Iterator - ArraySlice::begin( size_t i ) -{ - return array_.begin( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns an iterator to the first element of the arrayslice. -// -// \param i The row/column index. -// \return Iterator to the first element of the arrayslice. -// -// This function returns an iterator to the first element of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstIterator - ArraySlice::begin( size_t i ) const -{ - return array_.cbegin( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns an iterator to the first element of the arrayslice. -// -// \param i The row/column index. -// \return Iterator to the first element of the arrayslice. -// -// This function returns an iterator to the first element of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstIterator - ArraySlice::cbegin( size_t i ) const -{ - return array_.cbegin( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns an iterator just past the last element of the arrayslice. -// -// \param i The row/column index. -// \return Iterator just past the last element of the arrayslice. -// -// This function returns an iterator just past the last element of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::Iterator - ArraySlice::end( size_t i ) -{ - return array_.end( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns an iterator just past the last element of the arrayslice. -// -// \param i The row/column index. -// \return Iterator just past the last element of the arrayslice. -// -// This function returns an iterator just past the last element of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstIterator - ArraySlice::end( size_t i ) const -{ - return array_.cend( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns an iterator just past the last element of the arrayslice. -// -// \param i The row/column index. -// \return Iterator just past the last element of the arrayslice. -// -// This function returns an iterator just past the last element of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline typename ArraySlice::ConstIterator - ArraySlice::cend( size_t i ) const -{ - return array_.cend( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// ASSIGNMENT OPERATORS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Homogeneous assignment to all arrayslice elements. -// -// \param rhs Scalar value to be assigned to all arrayslice elements. -// \return Reference to the assigned arrayslice. -// -// This function homogeneously assigns the given value to all elements of the arrayslice. Note that in -// case the underlying dense array is a lower/upper array only lower/upper and diagonal elements -// of the underlying array are modified. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline ArraySlice& - ArraySlice::operator=( const ElementType& rhs ) -{ - decltype(auto) left( derestrict( array_ ) ); - - for (size_t i=0UL; i || trySet(*this, i, j, rhs)) - { - left(page(), i, j) = rhs; - } - } - } - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief List assignment to all arrayslice elements. -// -// \param list The initializer list. -// \exception std::invalid_argument Invalid assignment to arrayslice. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// This assignment operator offers the option to directly assign to all elements of the dense -// arrayslice by means of an initializer list. The arrayslice elements are assigned the values from the given -// initializer list. Missing values are reset to their default state. Note that in case the size -// of the initializer list exceeds the size of the arrayslice, a \a std::invalid_argument exception is -// thrown. Also, if the underlying array \a MT is restricted and the assignment would violate -// an invariant of the array, a \a std::invalid_argument exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline ArraySlice& - ArraySlice::operator=(nested_initializer_list list) -{ - if (list.size() > rows() || determineColumns(list) > columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to arrayslice" ); - } - - if( IsRestricted_v ) { - const InitializerArray tmp( list ); - if( !tryAssign( array_, tmp, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - } - - decltype(auto) left( derestrict( *this ) ); - - size_t i( 0UL ); - - for( const auto& rowList : list ) { - std::fill( std::copy( rowList.begin(), rowList.end(), left.begin( i ) ), left.end( i ), ElementType() ); - ++i; - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Copy assignment operator for ArraySlice. -// -// \param rhs Dense arrayslice to be copied. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument ArraySlice sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two arrayslices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline ArraySlice& - ArraySlice::operator=( const ArraySlice& rhs ) -{ - if( &rhs == this ) return *this; - - if( rows() != rhs.rows() || columns() != rhs.columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "ArraySlice sizes do not match" ); - } - - if( !tryAssign( array_, rhs, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsExpression_v && rhs.canAlias( &array_ ) ) { - const ResultType tmp( rhs ); - smpAssign( left, tmp ); - } - else { - smpAssign( left, rhs ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Assignment operator for different matrices. -// -// \param rhs Array to be assigned. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Array sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side matrix -inline ArraySlice& - ArraySlice::operator=( const Array& rhs ) -{ - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; - Right right( ~rhs ); - - if( !tryAssign( array_, right, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsReference_v && right.canAlias( &array_ ) ) { - const ResultType_t tmp( right ); - smpAssign( left, tmp ); - } - else { - if( IsSparseArray_v ) - reset(); - smpAssign( left, right ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Addition assignment operator for the addition of a matrix (\f$ \vec{a}+=\vec{b} \f$). -// -// \param rhs The right-hand side matrix to be added to the dense arrayslice. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Vector sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side matrix -inline ArraySlice& - ArraySlice::operator+=( const Array& rhs ) -{ - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; - Right right( ~rhs ); - - if( !tryAddAssign( array_, right, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsReference_v && right.canAlias( &array_ ) ) { - const ResultType_t tmp( right ); - smpAddAssign( left, tmp ); - } - else { - smpAddAssign( left, right ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ \vec{a}-=\vec{b} \f$). -// -// \param rhs The right-hand side matrix to be subtracted from the dense arrayslice. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Vector sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side matrix -inline ArraySlice& - ArraySlice::operator-=( const Array& rhs ) -{ - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; - Right right( ~rhs ); - - if( !trySubAssign( array_, right, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsReference_v && right.canAlias( &array_ ) ) { - const ResultType_t tmp( right ); - smpSubAssign( left, tmp ); - } - else { - smpSubAssign( left, right ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Schur product assignment operator for the multiplication of a matrix -// (\f$ \vec{a}\times=\vec{b} \f$). -// -// \param rhs The right-hand side matrix for the cross product. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Invalid matrix size for cross product. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current size of any of the two matrices is not equal to 3, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side matrix -inline ArraySlice& - ArraySlice::operator%=( const Array& rhs ) -{ - using blaze::assign; - - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - using SchurType = SchurTrait_t< ResultType, ResultType_t >; - - if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - if( !trySchurAssign( array_, (~rhs), 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsReference_v && (~rhs).canAlias( &array_ ) ) { - const SchurType tmp( *this % (~rhs) ); - smpSchurAssign( left, tmp ); - } - else { - smpSchurAssign( left, ~rhs ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Assignment operator for different matrices. -// -// \param rhs Array to be assigned. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Array sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2, bool TF, size_t M2, typename Enable > // Type of the right-hand side vector -inline ArraySlice& - ArraySlice::operator=( const Vector& rhs ) -{ - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - if( dimension<0>() != (~rhs).size() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; - Right right( ~rhs ); - - decltype(auto) left( derestrict( *this ) ); - - using ET = ElementType_t; - using custom_array = CustomArray<1, ET, false, true>; - - if( IsReference_v && right.canAlias( &array_ ) ) { - const ResultType_t tmp( right ); - smpAssign( left, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); - } - else { - if( IsSparseArray_v ) - reset(); - auto const& tmp = right; - smpAssign( left, custom_array( tmp.data(), tmp.size(), tmp.spacing() ) ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Assignment operator for different matrices. -// -// \param rhs Array to be assigned. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Array sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2, bool SO, size_t M2, typename Enable > // Type of the right-hand side matrix -inline ArraySlice& - ArraySlice::operator=( const Matrix& rhs ) -{ - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; - Right right( ~rhs ); - - if( !tryAssign( array_, right, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsReference_v && right.canAlias( &array_ ) ) { - const ResultType_t tmp( right ); - smpAssign( left, tmp ); - } - else { - if( IsSparseArray_v ) - reset(); - smpAssign( left, right ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Assignment operator for different matrices. -// -// \param rhs Array to be assigned. -// \return Reference to the assigned arrayslice. -// \exception std::invalid_argument Array sizes do not match. -// \exception std::invalid_argument Invalid assignment to restricted array. -// -// In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception -// is thrown. Also, if the underlying array \a MT is a lower or upper triangular array and the -// assignment would violate its lower or upper property, respectively, a \a std::invalid_argument -// exception is thrown. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2, size_t M2, typename Enable > // Type of the right-hand side tensor -inline ArraySlice& - ArraySlice::operator=( const Tensor& rhs ) -{ - //BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( ResultType_t ); - BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( ResultType_t ); - - if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { - BLAZE_THROW_INVALID_ARGUMENT( "Array sizes do not match" ); - } - - using Right = If_t< IsRestricted_v, CompositeType_t, const MT2& >; - Right right( ~rhs ); - - if( !tryAssign( array_, right, 0UL, 0UL, page() ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted array" ); - } - - decltype(auto) left( derestrict( *this ) ); - - if( IsReference_v && right.canAlias( &array_ ) ) { - const ResultType_t tmp( right ); - smpAssign( left, tmp ); - } - else { - if( IsSparseArray_v ) - reset(); - smpAssign( left, right ); - } - - BLAZE_INTERNAL_ASSERT( isIntact( array_ ), "Invariant violation detected" ); - - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// UTILITY FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the array containing the arrayslice. -// -// \return The array containing the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline MT& ArraySlice::operand() noexcept -{ - return array_; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the array containing the arrayslice. -// -// \return The array containing the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline const MT& ArraySlice::operand() const noexcept -{ - return array_; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the current size/dimension of the arrayslice. -// -// \return The size of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::rows() const noexcept -{ - return array_.rows(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the current size/dimension of the arrayslice. -// -// \return The size of the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::columns() const noexcept -{ - return array_.columns(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the minimum capacity of the arrayslice. -// -// \return The minimum capacity of the arrayslice. -// -// This function returns the minimum capacity of the arrayslice, which corresponds to the current size -// plus padding. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::spacing() const noexcept -{ - return array_.spacing(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the maximum capacity of the dense arrayslice. -// -// \return The maximum capacity of the dense arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::capacity() const noexcept -{ - return array_.capacity( 0UL, page() ) * array_.rows(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the maximum capacity of the dense arrayslice. -// -// \return The maximum capacity of the dense arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::capacity( size_t i ) const noexcept -{ - return array_.capacity( i, page() ) * array_.rows(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the number of non-zero elements in the arrayslice. -// -// \return The number of non-zero elements in the arrayslice. -// -// Note that the number of non-zero elements is always less than or equal to the current number -// of columns of the array containing the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::nonZeros() const -{ - size_t count ( 0 ); - for ( size_t i = 0; i < rows(); ++i ) { - count += array_.nonZeros( i, page() ); - } - return count; -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns the number of non-zero elements in the arrayslice. -// -// \return The number of non-zero elements in the arrayslice. -// -// Note that the number of non-zero elements is always less than or equal to the current number -// of columns of the array containing the arrayslice. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline size_t ArraySlice::nonZeros( size_t i ) const -{ - return array_.nonZeros( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Reset to the default initial values. -// -// \return void -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline void ArraySlice::reset() -{ - for ( size_t i = 0; i < rows(); ++i ) { - array_.reset( i, page() ); - } -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Reset to the default initial values. -// -// \return void -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline void ArraySlice::reset( size_t i ) -{ - array_.reset( i, page() ); -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// NUMERIC FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Scaling of the arrayslice by the scalar value \a scalar (\f$ \vec{a}=\vec{b}*s \f$). -// -// \param scalar The scalar value for the arrayslice scaling. -// \return Reference to the dense arrayslice. -// -// This function scales the arrayslice by applying the given scalar value \a scalar to each element -// of the arrayslice. For built-in and \c complex data types it has the same effect as using the -// multiplication assignment operator. Note that the function cannot be used to scale a arrayslice -// on a lower or upper unitriangular array. The attempt to scale such a arrayslice results in a -// compile time error! -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename Other > // Data type of the scalar value -inline ArraySlice& - ArraySlice::scale( const Other& scalar ) -{ - for ( size_t i = 0; i < rows(); ++i ) { - for ( size_t j = 0; j < columns(); ++j ) { - array_(page(), i, j) *= scalar; - } - } - return *this; -} -/*! \endcond */ -//************************************************************************************************* - - - - -//================================================================================================= -// -// EXPRESSION TEMPLATE EVALUATION FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the dense arrayslice can alias with the given address \a alias. -// -// \param alias The alias to be checked. -// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. -// -// This function returns whether the given address can alias with the dense arrayslice. In contrast -// to the isAliased() function this function is allowed to use compile time expressions to -// optimize the evaluation. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename Other > // Data type of the foreign expression -inline bool ArraySlice::canAlias( const Other* alias ) const noexcept -{ - return array_.isAliased( alias ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the dense arrayslice can alias with the given dense arrayslice \a alias. -// -// \param alias The alias to be checked. -// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. -// -// This function returns whether the given address can alias with the dense arrayslice. In contrast -// to the isAliased() function this function is allowed to use compile time expressions to -// optimize the evaluation. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< size_t M2 // Dimension of the ArraysSlice - , typename MT2 // Data type of the foreign dense arrayslice - , size_t... CRAs2 > // Compile time arrayslice arguments of the foreign dense arrayslice -inline bool - ArraySlice::canAlias( const ArraySlice* alias ) const noexcept -{ - return array_.isAliased( &alias->array_ ) && ( page() == alias->page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the dense arrayslice is aliased with the given address \a alias. -// -// \param alias The alias to be checked. -// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. -// -// This function returns whether the given address is aliased with the dense arrayslice. In contrast -// to the canAlias() function this function is not allowed to use compile time expressions to -// optimize the evaluation. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename Other > // Data type of the foreign expression -inline bool ArraySlice::isAliased( const Other* alias ) const noexcept -{ - return array_.isAliased( alias ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the dense arrayslice is aliased with the given dense arrayslice \a alias. -// -// \param alias The alias to be checked. -// \return \a true in case the alias corresponds to this dense arrayslice, \a false if not. -// -// This function returns whether the given address is aliased with the dense arrayslice. In contrast -// to the canAlias() function this function is not allowed to use compile time expressions to -// optimize the evaluation. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< size_t M2 // Dimension of the ArraysSlice - , typename MT2 // Data type of the foreign dense arrayslice - , size_t... CRAs2 > // Compile time arrayslice arguments of the foreign dense arrayslice -inline bool - ArraySlice::isAliased( const ArraySlice* alias ) const noexcept -{ - return array_.isAliased( &alias->array_ ) && ( page() == alias->page() ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the dense arrayslice is properly aligned in memory. -// -// \return \a true in case the dense arrayslice is aligned, \a false if not. -// -// This function returns whether the dense arrayslice is guaranteed to be properly aligned in memory, -// i.e. whether the beginning and the end of the dense arrayslice are guaranteed to conform to the -// alignment restrictions of the element type \a Type. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline bool ArraySlice::isAligned() const noexcept -{ - return array_.isAligned(); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Returns whether the dense arrayslice can be used in SMP assignments. -// -// \return \a true in case the dense arrayslice can be used in SMP assignments, \a false if not. -// -// This function returns whether the dense arrayslice can be used in SMP assignments. In contrast to -// the \a smpAssignable member enumeration, which is based solely on compile time information, -// this function additionally provides runtime information (as for instance the current size -// of the dense arrayslice). -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -inline bool ArraySlice::canSMPAssign() const noexcept -{ - return ( rows() * columns() > SMP_DMATASSIGN_THRESHOLD ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Load of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return The loaded SIMD element. -// -// This function performs a load of a specific SIMD element of the dense arrayslice. The index -// must be smaller than the number of array columns. This function must \b NOT be called -// explicitly! It is used internally for the performance optimized evaluation of expression -// templates. Calling this function explicitly might result in erroneous results and/or in -// compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE typename ArraySlice::SIMDType - ArraySlice::load( Dims... dims ) const noexcept -{ - return array_.load( page(), i, j ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Aligned load of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return The loaded SIMD element. -// -// This function performs an aligned load of a specific SIMD element of the dense arrayslice. -// The index must be smaller than the number of array columns. This function must \b NOT -// be called explicitly! It is used internally for the performance optimized evaluation of -// expression templates. Calling this function explicitly might result in erroneous results -// and/or in compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE typename ArraySlice::SIMDType - ArraySlice::loada( Dims... dims ) const noexcept -{ - return array_.loada( page(), i, j ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Unaligned load of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \return The loaded SIMD element. -// -// This function performs an unaligned load of a specific SIMD element of the dense arrayslice. -// The index must be smaller than the number of array columns. This function must \b NOT -// be called explicitly! It is used internally for the performance optimized evaluation of -// expression templates. Calling this function explicitly might result in erroneous results -// and/or in compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE typename ArraySlice::SIMDType - ArraySlice::loadu( Dims... dims ) const noexcept -{ - return array_.loadu( page(), i, j ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Store of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \param value The SIMD element to be stored. -// \return void -// -// This function performs a store a specific SIMD element of the dense arrayslice. The index -// must be smaller than the number of array columns. This function must \b NOT be called -// explicitly! It is used internally for the performance optimized evaluation of expression -// templates. Calling this function explicitly might result in erroneous results and/or in -// compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE void - ArraySlice::store( const SIMDType& value, Dims... dims ) noexcept -{ - array_.store( page(), i, j, value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Aligned store of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \param value The SIMD element to be stored. -// \return void -// -// This function performs an aligned store a specific SIMD element of the dense arrayslice. The -// index must be smaller than the number of array columns. This function must \b NOT be -// called explicitly! It is used internally for the performance optimized evaluation of -// expression templates. Calling this function explicitly might result in erroneous results -// and/or in compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE void - ArraySlice::storea( const SIMDType& value, Dims... dims ) noexcept -{ - array_.storea( page(), i, j, value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Unligned store of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \param value The SIMD element to be stored. -// \return void -// -// This function performs an unaligned store a specific SIMD element of the dense arrayslice. -// The index must be smaller than the number of array columns. This function must \b NOT -// be called explicitly! It is used internally for the performance optimized evaluation of -// expression templates. Calling this function explicitly might result in erroneous results -// and/or in compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE void - ArraySlice::storeu( const SIMDType& value, Dims... dims ) noexcept -{ - array_.storeu( page(), i, j, value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Aligned, non-temporal store of a SIMD element of the dense arrayslice. -// -// \param index Access index. The index must be smaller than the number of array columns. -// \param value The SIMD element to be stored. -// \return void -// -// This function performs an aligned, non-temporal store a specific SIMD element of the dense -// arrayslice. The index must be smaller than the number of array columns. This function must \b NOT -// be called explicitly! It is used internally for the performance optimized evaluation of -// expression templates. Calling this function explicitly might result in erroneous results -// and/or in compilation errors. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename... Dims > -BLAZE_ALWAYS_INLINE void - ArraySlice::stream( const SIMDType& value, Dims... dims ) noexcept -{ - array_.stream( page(), i, j, value ); -} -/*! \endcond */ -//************************************************************************************************* - - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Default implementation of the assignment of a dense matrix. -// -// \param rhs The right-hand side dense matrix to be assigned. -// \return void -// -// This function must \b NOT be called explicitly! It is used internally for the performance -// optimized evaluation of expression templates. Calling this function explicitly might result -// in erroneous results and/or in compilation errors. Instead of using this function use the -// assignment operator. -*/ -template< size_t M // Dimension of the ArraysSlice - , typename MT // Type of the dense array - , size_t... CRAs > // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::assign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedAssign_v > -{ - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows(), "Invalid matrix sizes" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid matrix sizes" ); - - for (size_t i = 0UL; i < (~rhs).rows(); ++i ) { - const size_t jpos( (~rhs).columns() & size_t(-2) ); - for( size_t j=0UL; j // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::assign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); - - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - constexpr bool remainder( !IsPadded_v || !IsPadded_v ); - - const size_t cols( columns() ); - - for (size_t i = 0; i < (~rhs).rows(); ++i) { - const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); - BLAZE_INTERNAL_ASSERT( !remainder || ( cols - ( cols % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); - - size_t j( 0UL ); - Iterator left( begin(i) ); - ConstIterator_t right( (~rhs).begin(i) ); - - if( useStreaming && cols > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &array_ ) ) - { - for( ; j // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::addAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedAddAssign_v > -{ - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - for (size_t i = 0UL; i < (~rhs).rows(); ++i ) { - const size_t jpos( (~rhs).columns() & size_t(-2) ); - for( size_t j=0UL; j // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::addAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedAddAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); - - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - constexpr bool remainder( !IsPadded_v || !IsPadded_v ); - - const size_t cols( columns() ); - - for (size_t i = 0; i < (~rhs).rows(); ++i) { - const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); - BLAZE_INTERNAL_ASSERT( !remainder || ( cols - ( cols % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); - - size_t j( 0UL ); - Iterator left( begin(i) ); - ConstIterator_t right( (~rhs).begin(i) ); - - for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) { - left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE; - } - for( ; j // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::subAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedSubAssign_v > -{ - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - for (size_t i = 0UL; i < (~rhs).rows(); ++i ) { - const size_t jpos( (~rhs).columns() & size_t(-2) ); - for( size_t j=0UL; j // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::subAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedSubAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); - - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - constexpr bool remainder( !IsPadded_v || !IsPadded_v ); - - const size_t cols( columns() ); - - for (size_t i = 0; i < (~rhs).rows(); ++i) { - const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); - BLAZE_INTERNAL_ASSERT( !remainder || ( cols - ( cols % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); - - size_t j( 0UL ); - Iterator left( begin(i) ); - ConstIterator_t right( (~rhs).begin(i) ); - - for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) { - left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE; - } - for( ; j // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::schurAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedSchurAssign_v > -{ - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - const size_t jpos( columns() & size_t(-2) ); - BLAZE_INTERNAL_ASSERT( ( columns() - ( columns() % 2UL ) ) == jpos, "Invalid end calculation" ); - - for( size_t i=0UL; i // Compile time arrayslice arguments -template< typename MT2 > // Type of the right-hand side dense matrix -inline auto ArraySlice::schurAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedSchurAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); - - BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); - BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); - - constexpr bool remainder( !IsPadded_v || !IsPadded_v ); - - const size_t cols( columns() ); - - for( size_t i=0UL; i right( (~rhs).begin(i) ); - - for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) { - left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; - left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE; - } - for( ; j::assign( const DenseTensor& rhs ) constexpr bool remainder( !IsPadded_v || !IsPadded_v ); const size_t cols( columns() ); + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); for( size_t k=0UL; k::assign( const DenseTensor& rhs ) { size_t j(0UL); Iterator left(begin(i, k)); - ConstIterator_t right((~rhs).begin(i, k)); + ConstIterator_t right((~rhs).begin(i, k)); if (useStreaming && cols > (cacheSize / (sizeof(ElementType) * 3UL)) && !(~rhs).isAliased(&quaternion_)) { @@ -1831,6 +1832,7 @@ inline auto QuatSlice::addAssign( const DenseTensor& rhs ) constexpr bool remainder( !IsPadded_v || !IsPadded_v ); const size_t cols( columns() ); + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); for( size_t k=0UL; k::addAssign( const DenseTensor& rhs ) { size_t j(0UL); Iterator left(begin(i, k)); - ConstIterator_t right((~rhs).begin(i, k)); + ConstIterator_t right((~rhs).begin(i, k)); for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; @@ -1924,6 +1926,7 @@ inline auto QuatSlice::subAssign( const DenseTensor& rhs ) constexpr bool remainder( !IsPadded_v || !IsPadded_v ); const size_t cols( columns() ); + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); for( size_t k=0UL; k::subAssign( const DenseTensor& rhs ) { size_t j(0UL); Iterator left(begin(i, k)); - ConstIterator_t right((~rhs).begin(i, k)); + ConstIterator_t right((~rhs).begin(i, k)); for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; @@ -2017,6 +2020,7 @@ inline auto QuatSlice::schurAssign( const DenseTensor& rhs ) constexpr bool remainder( !IsPadded_v || !IsPadded_v ); const size_t cols( columns() ); + const size_t jpos( ( remainder )?( cols & size_t(-SIMDSIZE) ):( cols ) ); for( size_t k=0UL; k::schurAssign( const DenseTensor& rhs ) { size_t j(0UL); Iterator left(begin(i, k)); - ConstIterator_t right((~rhs).begin(i, k)); + ConstIterator_t right((~rhs).begin(i, k)); for (; (j + SIMDSIZE * 3UL) < jpos; j += SIMDSIZE * 4UL) { left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; diff --git a/blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h b/blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h deleted file mode 100644 index f15e15b..0000000 --- a/blazetest/blazetest/mathtest/arrayslice/DenseGeneralTest.h +++ /dev/null @@ -1,432 +0,0 @@ -//================================================================================================= -/*! -// \file blazetest/mathtest/arrayslice/DenseGeneralTest.h -// \brief Header file for the ArraySlice dense general test -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - -#ifndef _BLAZETEST_MATHTEST_ARRAYSLICE_DENSEGENERALTEST_H_ -#define _BLAZETEST_MATHTEST_ARRAYSLICE_DENSEGENERALTEST_H_ - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include -#include - -#include -#include -#include - -namespace blazetest { - -namespace mathtest { - -namespace arrayslice { - -//================================================================================================= -// -// CLASS DEFINITION -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Auxiliary class for all tests of the dense general ArraySlice specialization. -// -// This class represents a test suite for the blaze::ArraySlice class template specialization for -// dense general matrices. It performs a series of both compile time as well as runtime tests. -*/ -class DenseGeneralTest -{ - public: - //**Constructors******************************************************************************** - /*!\name Constructors */ - //@{ - explicit DenseGeneralTest(); - // No explicitly declared copy constructor. - //@} - //********************************************************************************************** - - //**Destructor********************************************************************************** - // No explicitly declared destructor. - //********************************************************************************************** - - private: - //**Test functions****************************************************************************** - /*!\name Test functions */ - //@{ - void testConstructors(); - void testAssignment(); - void testAddAssign(); - void testSubAssign(); - void testMultAssign(); - void testSchurAssign(); - void testScaling(); - void testFunctionCall(); - void testAt(); - void testIterator(); - void testNonZeros(); - void testReset(); - void testClear(); - void testIsDefault(); - void testIsSame(); - void testSubmatrix(); - void testRow(); - void testRows(); - void testColumn(); - void testColumns(); - void testBand(); - - template< typename Type > - void checkSize( const Type& arrayslice, size_t expectedSize ) const; - - template< typename Type > - void checkRows( const Type& array, size_t expectedRows ) const; - - template< typename Type > - void checkColumns( const Type& array, size_t expectedColumns ) const; - - template< typename Type > - void checkPages( const Type& array, size_t expectedPages ) const; - - template< typename Type > - void checkCapacity( const Type& object, size_t minCapacity ) const; - - template< typename Type > - void checkNonZeros( const Type& object, size_t expectedNonZeros ) const; - - template< typename Type > - void checkNonZeros( const Type& array, size_t i, size_t k, size_t expectedNonZeros ) const; - //@} - //********************************************************************************************** - - //**Utility functions*************************************************************************** - /*!\name Utility functions */ - //@{ - void initialize(); - //@} - //********************************************************************************************** - - //**Type definitions**************************************************************************** - using MT = blaze::DynamicArray<3, int>; //!< Dynamic array type. - using RT = blaze::ArraySlice<2, MT>; //!< Dense arrayslice type for arrays (slice along largest dimension). - //********************************************************************************************** - - //**Member variables**************************************************************************** - /*!\name Member variables */ - //@{ - MT mat_; //!< dynamic array. - std::string test_; //!< Label of the currently performed test. - //@} - //********************************************************************************************** - - //**Compile time checks************************************************************************* - /*! \cond BLAZE_INTERNAL */ - BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( MT ); - BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE ( RT ); - /*! \endcond */ - //********************************************************************************************** -}; -//************************************************************************************************* - - - - -//================================================================================================= -// -// TEST FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Checking the size of the given dense arrayslice. -// -// \param arrayslice The dense arrayslice to be checked. -// \param expectedSize The expected size of the dense arrayslice. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the size of the given dense arrayslice. In case the actual size does not -// correspond to the given expected size, a \a std::runtime_error exception is thrown. -*/ -template< typename Type > // Type of the dense arrayslice -void DenseGeneralTest::checkSize( const Type& arrayslice, size_t expectedSize ) const -{ - if( size( arrayslice ) != expectedSize ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid size detected\n" - << " Details:\n" - << " Size : " << size( arrayslice ) << "\n" - << " Expected size: " << expectedSize << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Checking the number of arrayslices of the given dynamic array. -// -// \param array The dynamic array to be checked. -// \param expectedArraySlices The expected number of rows of the dynamic array. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the number of rows of the given dynamic array. In case the actual number -// of arrayslices does not correspond to the given expected number of arrayslices, a \a std::runtime_error -// exception is thrown. -*/ -template< typename Type > // Type of the dynamic array -void DenseGeneralTest::checkRows( const Type& array, size_t expectedRows ) const -{ - if( rows( array ) != expectedRows ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of rows detected\n" - << " Details:\n" - << " Number of rows : " << rows( array ) << "\n" - << " Expected number of rows: " << expectedRows << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Checking the number of columns of the given dynamic array. -// -// \param array The dynamic array to be checked. -// \param expectedColumns The expected number of columns of the dynamic array. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the number of columns of the given dynamic array. In case the -// actual number of columns does not correspond to the given expected number of columns, -// a \a std::runtime_error exception is thrown. -*/ -template< typename Type > // Type of the dynamic array -void DenseGeneralTest::checkColumns( const Type& array, size_t expectedColumns ) const -{ - if( columns( array ) != expectedColumns ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of columns detected\n" - << " Details:\n" - << " Number of columns : " << columns( array ) << "\n" - << " Expected number of columns: " << expectedColumns << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Checking the number of pages of the given dynamic array. -// -// \param array The dynamic array to be checked. -// \param expectedPages The expected number of columns of the dynamic array. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the number of pages of the given dynamic array. In case the -// actual number of pages does not correspond to the given expected number of pages, -// a \a std::runtime_error exception is thrown. -*/ -template< typename Type > // Type of the dynamic array -void DenseGeneralTest::checkPages( const Type& array, size_t expectedPages ) const -{ - if( pages( array ) != expectedPages ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of pages detected\n" - << " Details:\n" - << " Number of pages : " << pages( array ) << "\n" - << " Expected number of pages: " << expectedPages << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Checking the capacity of the given dense arrayslice or dynamic array. -// -// \param object The dense arrayslice or dynamic array to be checked. -// \param minCapacity The expected minimum capacity. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the capacity of the given dense arrayslice or dynamic array. In case the actual -// capacity is smaller than the given expected minimum capacity, a \a std::runtime_error exception -// is thrown. -*/ -template< typename Type > // Type of the dense arrayslice or dynamic array -void DenseGeneralTest::checkCapacity( const Type& object, size_t minCapacity ) const -{ - if( capacity( object ) < minCapacity ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid capacity detected\n" - << " Details:\n" - << " Capacity : " << capacity( object ) << "\n" - << " Expected minimum capacity: " << minCapacity << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Checking the number of non-zero elements of the given dense arrayslice or dynamic array. -// -// \param object The dense arrayslice or dynamic array to be checked. -// \param expectedNonZeros The expected number of non-zero elements. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the number of non-zero elements of the given dense arrayslice. In case the -// actual number of non-zero elements does not correspond to the given expected number, a -// \a std::runtime_error exception is thrown. -*/ -template< typename Type > // Type of the dense arrayslice or dynamic array -void DenseGeneralTest::checkNonZeros( const Type& object, size_t expectedNonZeros ) const -{ - if( nonZeros( object ) != expectedNonZeros ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of non-zero elements\n" - << " Details:\n" - << " Number of non-zeros : " << nonZeros( object ) << "\n" - << " Expected number of non-zeros: " << expectedNonZeros << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( capacity( object ) < nonZeros( object ) ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid capacity detected\n" - << " Details:\n" - << " Number of non-zeros: " << nonZeros( object ) << "\n" - << " Capacity : " << capacity( object ) << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Checking the number of non-zero elements in a specific arrayslice/column of the given dynamic array. -// -// \param array The dynamic array to be checked. -// \param index The arrayslice/column to be checked. -// \param expectedNonZeros The expected number of non-zero elements in the specified arrayslice/column. -// \return void -// \exception std::runtime_error Error detected. -// -// This function checks the number of non-zero elements in the specified arrayslice/column of the -// given dynamic array. In case the actual number of non-zero elements does not correspond -// to the given expected number, a \a std::runtime_error exception is thrown. -*/ -template< typename Type > // Type of the dynamic array -void DenseGeneralTest::checkNonZeros( const Type& array, size_t i, size_t k, size_t expectedNonZeros ) const -{ - if( nonZeros( array, i, k ) != expectedNonZeros ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of non-zero elements in row " << i << " page " << k << "\n" - << " Details:\n" - << " Number of non-zeros : " << nonZeros( array, i, k ) << "\n" - << " Expected number of non-zeros: " << expectedNonZeros << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( capacity( array, i, k ) < nonZeros( array, i, k ) ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid capacity detected in row " << i << " page " << k << "\n" - << " Details:\n" - << " Number of non-zeros: " << nonZeros( array, i, k ) << "\n" - << " Capacity : " << capacity( array, i, k ) << "\n"; - throw std::runtime_error( oss.str() ); - } -} -//************************************************************************************************* - - - - -//================================================================================================= -// -// GLOBAL TEST FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Testing the functionality of the dense general ArraySlice specialization. -// -// \return void -*/ -void runTest() -{ - DenseGeneralTest(); -} -//************************************************************************************************* - - - - -//================================================================================================= -// -// MACRO DEFINITIONS -// -//================================================================================================= - -//************************************************************************************************* -/*! \cond BLAZE_INTERNAL */ -/*!\brief Macro for the execution of the ArraySlice dense general test. -*/ -#define RUN_ARRAYSLICE_DENSEGENERAL_TEST \ - blazetest::mathtest::arrayslice::runTest() -/*! \endcond */ -//************************************************************************************************* - -} // namespace arrayslice - -} // namespace mathtest - -} // namespace blazetest - -#endif diff --git a/blazetest/src/mathtest/CMakeLists.txt b/blazetest/src/mathtest/CMakeLists.txt index 9bad886..f0bda16 100644 --- a/blazetest/src/mathtest/CMakeLists.txt +++ b/blazetest/src/mathtest/CMakeLists.txt @@ -31,7 +31,6 @@ # ================================================================================================= set(subdirs - arrayslice columnslice customarray customtensor diff --git a/blazetest/src/mathtest/arrayslice/CMakeLists.txt b/blazetest/src/mathtest/arrayslice/CMakeLists.txt deleted file mode 100644 index 6d5f612..0000000 --- a/blazetest/src/mathtest/arrayslice/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# ================================================================================================= -# -# Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -# Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -# -# This file is part of the Blaze library. You can redistribute it and/or modify it under -# the terms of the New (Revised) BSD License. Redistribution and use in source and binary -# forms, with or without modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright notice, this list of -# conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, this list -# of conditions and the following disclaimer in the documentation and/or other materials -# provided with the distribution. -# 3. Neither the names of the Blaze development group nor the names of its contributors -# may be used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -# DAMAGE. -# -# ================================================================================================= - -set(category ArraySlice) - -set(tests - DenseGeneralTest - IncludeTest -) - -foreach(test ${tests}) - add_blaze_tensor_test(${category}${test} - SOURCES ${test}.cpp - FOLDER "Tests/${category}") -endforeach() diff --git a/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp deleted file mode 100644 index ffdc5f1..0000000 --- a/blazetest/src/mathtest/arrayslice/DenseGeneralTest.cpp +++ /dev/null @@ -1,5156 +0,0 @@ -//================================================================================================= -/*! -// \file src/mathtest/arrayslice/DenseGeneralTest.cpp -// \brief Source file for the ArraySlice dense general test -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include -#include -#include - -#include -#include -#include -#include -#include - -// #include -#include -#include - -#include - - -namespace blazetest { - -namespace mathtest { - -namespace arrayslice { - -//================================================================================================= -// -// CONSTRUCTORS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Constructor for the ArraySlice dense general test. -// -// \exception std::runtime_error Operation error detected. -*/ -DenseGeneralTest::DenseGeneralTest() - : mat_ ( 2UL, 5UL, 4UL ) -{ - testConstructors(); - testAssignment(); - testAddAssign(); - testSubAssign(); - testMultAssign(); - testSchurAssign(); - testScaling(); - testFunctionCall(); - testAt(); - testIterator(); - testNonZeros(); - testReset(); - testClear(); - testIsDefault(); - testIsSame(); - testSubmatrix(); - testRow(); - testRows(); - testColumn(); - testColumns(); -} -//************************************************************************************************* - - - - -//================================================================================================= -// -// TEST FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Test of the ArraySlice constructors. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of all constructors of the ArraySlice specialization. In case an -// error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testConstructors() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "ArraySlice constructor (0x0)"; - - MT mat; - - // 0th matrix arrayslice - try { - blaze::arrayslice<2>( mat, 0UL ); - } - catch( std::invalid_argument& ) {} - } - - { - test_ = "ArraySlice constructor (2x0)"; - - MT mat( 2UL, 2UL, 0UL ); - - // 0th matrix arrayslice - { - RT arrayslice0 = blaze::arrayslice<2>( mat, 0UL ); - - checkRows ( arrayslice0, 2UL ); - checkColumns ( arrayslice0, 0UL ); - checkCapacity( arrayslice0, 0UL ); - checkNonZeros( arrayslice0, 0UL ); - } - - // 1st matrix arrayslice - { - RT arrayslice1 = blaze::arrayslice<2>( mat, 1UL ); - - checkRows ( arrayslice1, 2UL ); - checkColumns ( arrayslice1, 0UL ); - checkCapacity( arrayslice1, 0UL ); - checkNonZeros( arrayslice1, 0UL ); - } - - // 2nd matrix arrayslice - try { - blaze::arrayslice<2>( mat, 2UL ); - } - catch( std::invalid_argument& ) {} - } - - { - test_ = "ArraySlice constructor (5x4)"; - - initialize(); - - // 0th tensor arrayslice - { - RT arrayslice0 = blaze::arrayslice<2>( mat_, 0UL ); - - checkRows ( arrayslice0, 5UL ); - checkColumns ( arrayslice0, 4UL ); - checkCapacity( arrayslice0, 20UL ); - checkNonZeros( arrayslice0, 10UL ); - - if( arrayslice0(0,0) != 0 || arrayslice0(0,1) != 0 || arrayslice0(0,2) != 0 || arrayslice0(0,3) != 0 || - arrayslice0(1,0) != 0 || arrayslice0(1,1) != 1 || arrayslice0(1,2) != 0 || arrayslice0(1,3) != 0 || - arrayslice0(2,0) != -2 || arrayslice0(2,1) != 0 || arrayslice0(2,2) != -3 || arrayslice0(2,3) != 0 || - arrayslice0(3,0) != 0 || arrayslice0(3,1) != 4 || arrayslice0(3,2) != 5 || arrayslice0(3,3) != -6 || - arrayslice0(4,0) != 7 || arrayslice0(4,1) != -8 || arrayslice0(4,2) != 9 || arrayslice0(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of 0th dense arrayslice failed\n" - << " Details:\n" - << " Result:\n" << arrayslice0 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // 1st tensor arrayslice - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - - checkRows ( arrayslice1, 5UL ); - checkColumns ( arrayslice1, 4UL ); - checkCapacity( arrayslice1, 20UL ); - checkNonZeros( arrayslice1, 10UL ); - - if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 0 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 0 || - arrayslice1(1,0) != 0 || arrayslice1(1,1) != 1 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || - arrayslice1(2,0) != -2 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != -3 || arrayslice1(2,3) != 0 || - arrayslice1(3,0) != 0 || arrayslice1(3,1) != 4 || arrayslice1(3,2) != 5 || arrayslice1(3,3) != -6 || - arrayslice1(4,0) != 7 || arrayslice1(4,1) != -8 || arrayslice1(4,2) != 9 || arrayslice1(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of 1st dense arrayslice failed\n" - << " Details:\n" - << " Result:\n" << arrayslice1 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // 2nd tensor arrayslice - try { - RT arrayslice2 = blaze::arrayslice<2>( mat_, 2UL ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Out-of-bound page access succeeded\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - -//************************************************************************************************* -/*!\brief Test of the ArraySlice assignment operators. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of all assignment operators of the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testAssignment() -{ - //===================================================================================== - // homogeneous assignment - //===================================================================================== - - { - test_ = "ArraySlice homogeneous assignment"; - - initialize(); - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice1 = 8; - - - checkRows ( arrayslice1, 5UL ); - checkColumns ( arrayslice1, 4UL ); - checkCapacity( arrayslice1, 20UL ); - checkNonZeros( arrayslice1, 20UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 30UL ); - - if( arrayslice1(0,0) != 8 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 8 || arrayslice1(0,3) != 8 || - arrayslice1(1,0) != 8 || arrayslice1(1,1) != 8 || arrayslice1(1,2) != 8 || arrayslice1(1,3) != 8 || - arrayslice1(2,0) != 8 || arrayslice1(2,1) != 8 || arrayslice1(2,2) != 8 || arrayslice1(2,3) != 8 || - arrayslice1(3,0) != 8 || arrayslice1(3,1) != 8 || arrayslice1(3,2) != 8 || arrayslice1(3,3) != 8 || - arrayslice1(4,0) != 8 || arrayslice1(4,1) != 8 || arrayslice1(4,2) != 8 || arrayslice1(4,3) != 8 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice1 << "\n" - << " Expected result:\n(( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 8 || mat_(1,0,1) != 8 || mat_(1,0,2) != 8 || mat_(1,0,3) != 8 || - mat_(1,1,0) != 8 || mat_(1,1,1) != 8 || mat_(1,1,2) != 8 || mat_(1,1,3) != 8 || - mat_(1,2,0) != 8 || mat_(1,2,1) != 8 || mat_(1,2,2) != 8 || mat_(1,2,3) != 8 || - mat_(1,3,0) != 8 || mat_(1,3,1) != 8 || mat_(1,3,2) != 8 || mat_(1,3,3) != 8 || - mat_(1,4,0) != 8 || mat_(1,4,1) != 8 || mat_(1,4,2) != 8 || mat_(1,4,3) != 8 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 8 8 8 8 )\n" - " ( 8 8 8 8 )\n" - " ( 8 8 8 8 )\n" - " ( 8 8 8 8 )\n" - " ( 8 8 8 8 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // list assignment - //===================================================================================== - - { - test_ = "initializer list assignment (complete list)"; - - initialize(); - - RT arrayslice3 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice3 = { - {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} - }; - - checkRows ( arrayslice3, 5UL ); - checkColumns ( arrayslice3, 4UL ); - checkCapacity( arrayslice3, 20UL ); - checkNonZeros( arrayslice3, 20UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 30UL ); - - if( arrayslice3(0,0) != 1 || arrayslice3(0,1) != 2 || arrayslice3(0,2) != 3 || arrayslice3(0,3) != 4 || - arrayslice3(1,0) != 1 || arrayslice3(1,1) != 2 || arrayslice3(1,2) != 3 || arrayslice3(1,3) != 4 || - arrayslice3(2,0) != 1 || arrayslice3(2,1) != 2 || arrayslice3(2,2) != 3 || arrayslice3(2,3) != 4 || - arrayslice3(3,0) != 1 || arrayslice3(3,1) != 2 || arrayslice3(3,2) != 3 || arrayslice3(3,3) != 4 || - arrayslice3(4,0) != 1 || arrayslice3(4,1) != 2 || arrayslice3(4,2) != 3 || arrayslice3(4,3) != 4 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice3 << "\n" - << " Expected result:\n(( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 1 || mat_(1,0,1) != 2 || mat_(1,0,2) != 3 || mat_(1,0,3) != 4 || - mat_(1,1,0) != 1 || mat_(1,1,1) != 2 || mat_(1,1,2) != 3 || mat_(1,1,3) != 4 || - mat_(1,2,0) != 1 || mat_(1,2,1) != 2 || mat_(1,2,2) != 3 || mat_(1,2,3) != 4 || - mat_(1,3,0) != 1 || mat_(1,3,1) != 2 || mat_(1,3,2) != 3 || mat_(1,3,3) != 4 || - mat_(1,4,0) != 1 || mat_(1,4,1) != 2 || mat_(1,4,2) != 3 || mat_(1,4,3) != 4 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 1 2 3 4 )\n" - " ( 1 2 3 4 )\n" - " ( 1 2 3 4 )\n" - " ( 1 2 3 4 )\n" - " ( 1 2 3 4 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "initializer list assignment (incomplete list)"; - - initialize(); - - RT arrayslice3 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice3 = {{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}}; - - checkRows ( arrayslice3, 5UL ); - checkColumns ( arrayslice3, 4UL ); - checkCapacity( arrayslice3, 20UL ); - checkNonZeros( arrayslice3, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice3(0,0) != 1 || arrayslice3(0,1) != 2 || arrayslice3(0,2) != 0 || arrayslice3(0,3) != 0 || - arrayslice3(1,0) != 1 || arrayslice3(1,1) != 2 || arrayslice3(1,2) != 0 || arrayslice3(1,3) != 0 || - arrayslice3(2,0) != 1 || arrayslice3(2,1) != 2 || arrayslice3(2,2) != 0 || arrayslice3(2,3) != 0 || - arrayslice3(3,0) != 1 || arrayslice3(3,1) != 2 || arrayslice3(3,2) != 0 || arrayslice3(3,3) != 0 || - arrayslice3(4,0) != 1 || arrayslice3(4,1) != 2 || arrayslice3(4,2) != 0 || arrayslice3(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice3 << "\n" - << " Expected result:\n(( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 1 || mat_(1,0,1) != 2 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 1 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 1 || mat_(1,2,1) != 2 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 1 || mat_(1,3,1) != 2 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 1 || mat_(1,4,1) != 2 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 1 2 0 0 )\n" - " ( 1 2 0 0 )\n" - " ( 1 2 0 0 )\n" - " ( 1 2 0 0 )\n" - " ( 1 2 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // copy assignment - //===================================================================================== - - { - test_ = "ArraySlice copy assignment"; - - initialize(); - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 0UL ); - arrayslice1 = 0; - arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - - checkRows ( arrayslice1, 5UL ); - checkColumns ( arrayslice1, 4UL ); - checkCapacity( arrayslice1, 20UL ); - checkNonZeros( arrayslice1, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 0 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 0 || - arrayslice1(1,0) != 0 || arrayslice1(1,1) != 1 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || - arrayslice1(2,0) != -2 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != -3 || arrayslice1(2,3) != 0 || - arrayslice1(3,0) != 0 || arrayslice1(3,1) != 4 || arrayslice1(3,2) != 5 || arrayslice1(3,3) != -6 || - arrayslice1(4,0) != 7 || arrayslice1(4,1) != -8 || arrayslice1(4,2) != 9 || arrayslice1(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice1 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // dense array assignment - //===================================================================================== - - { - test_ = "dense array assignment (mixed type)"; - - initialize(); - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - - blaze::DynamicArray<2, int> m1; - m1 = {{0, 8, 0, 9}, {0}, {0}, {0}, {0}}; - - arrayslice1 = m1; - - checkRows ( arrayslice1, 5UL ); - checkColumns ( arrayslice1, 4UL ); - checkCapacity( arrayslice1, 20UL ); - checkNonZeros( arrayslice1, 2UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 12UL ); - - if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 9 || - arrayslice1(1,0) != 0 || arrayslice1(1,1) != 0 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || - arrayslice1(2,0) != 0 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != 0 || arrayslice1(2,3) != 0 || - arrayslice1(3,0) != 0 || arrayslice1(3,1) != 0 || arrayslice1(3,2) != 0 || arrayslice1(3,3) != 0 || - arrayslice1(4,0) != 0 || arrayslice1(4,1) != 0 || arrayslice1(4,2) != 0 || arrayslice1(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice1 << "\n" - << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 8 || mat_(1,0,2) != 0 || mat_(1,0,3) != 9 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 9 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array assignment (aligned/padded)"; - - using blaze::aligned; - using blaze::padded; - using blaze::rowMajor; - - initialize(); - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - - using AlignedPadded = blaze::CustomMatrix; - std::unique_ptr memory( blaze::allocate( 80UL ) ); - AlignedPadded m1( memory.get(), 5UL, 4UL, 16UL ); - m1 = 0; - m1(0,0) = 0; - m1(0,1) = 8; - m1(0,2) = 0; - m1(0,3) = 9; - - arrayslice1 = m1; - - checkRows ( arrayslice1, 5UL ); - checkColumns ( arrayslice1, 4UL ); - checkCapacity( arrayslice1, 20UL ); - checkNonZeros( arrayslice1, 2UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 12UL ); - - if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 9 || - arrayslice1(1,0) != 0 || arrayslice1(1,1) != 0 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || - arrayslice1(2,0) != 0 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != 0 || arrayslice1(2,3) != 0 || - arrayslice1(3,0) != 0 || arrayslice1(3,1) != 0 || arrayslice1(3,2) != 0 || arrayslice1(3,3) != 0 || - arrayslice1(4,0) != 0 || arrayslice1(4,1) != 0 || arrayslice1(4,2) != 0 || arrayslice1(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice1 << "\n" - << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 8 || mat_(1,0,2) != 0 || mat_(1,0,3) != 9 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 9 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array assignment (unaligned/unpadded)"; - - using blaze::unaligned; - using blaze::unpadded; - using blaze::rowMajor; - - initialize(); - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - - using UnalignedUnpadded = blaze::CustomMatrix; - std::unique_ptr memory( new int[21] ); - UnalignedUnpadded m1( memory.get()+1UL, 5UL, 4UL ); - m1 = 0; - m1(0,0) = 0; - m1(0,1) = 8; - m1(0,2) = 0; - m1(0,3) = 9; - - arrayslice1 = m1; - - checkRows ( arrayslice1, 5UL ); - checkColumns ( arrayslice1, 4UL ); - checkCapacity( arrayslice1, 20UL ); - checkNonZeros( arrayslice1, 2UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 12UL ); - - if( arrayslice1(0,0) != 0 || arrayslice1(0,1) != 8 || arrayslice1(0,2) != 0 || arrayslice1(0,3) != 9 || - arrayslice1(1,0) != 0 || arrayslice1(1,1) != 0 || arrayslice1(1,2) != 0 || arrayslice1(1,3) != 0 || - arrayslice1(2,0) != 0 || arrayslice1(2,1) != 0 || arrayslice1(2,2) != 0 || arrayslice1(2,3) != 0 || - arrayslice1(3,0) != 0 || arrayslice1(3,1) != 0 || arrayslice1(3,2) != 0 || arrayslice1(3,3) != 0 || - arrayslice1(4,0) != 0 || arrayslice1(4,1) != 0 || arrayslice1(4,2) != 0 || arrayslice1(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice1 << "\n" - << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 8 || mat_(1,0,2) != 0 || mat_(1,0,3) != 9 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 9 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice addition assignment operators. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the addition assignment operators of the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testAddAssign() -{ - //===================================================================================== - // ArraySlice addition assignment - //===================================================================================== - - { - test_ = "ArraySlice addition assignment"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 += blaze::arrayslice<2>( mat_, 0UL ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || - arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || - mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 2 0 0 )\n" - " ( -4 0 -6 0 )\n" - " ( 0 8 10 -12 )\n" - " ( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // dense array addition assignment - //===================================================================================== - - { - test_ = "dense array addition assignment (mixed type)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - const blaze::DynamicMatrix vec{{0, 0, 0, 0}, - {0, 1, 0, 0}, - {-2, 0, -3, 0}, - {0, 4, 5, -6}, - {7, -8, 9, 10}}; - - arrayslice2 += vec; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || - arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || - mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 2 0 0 )\n" - " ( -4 0 -6 0 )\n" - " ( 0 8 10 -12 )\n" - " ( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array addition assignment (aligned/padded)"; - - using blaze::aligned; - using blaze::padded; - using blaze::rowMajor; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - using AlignedPadded = blaze::CustomMatrix; - std::unique_ptr memory( blaze::allocate( 80UL ) ); - AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); - m(0,0) = 0; - m(0,1) = 0; - m(0,2) = 0; - m(0,3) = 0; - m(1,0) = 0; - m(1,1) = 1; - m(1,2) = 0; - m(1,3) = 0; - m(2,0) = -2; - m(2,1) = 0; - m(2,2) = -3; - m(2,3) = 0; - m(3,0) = 0; - m(3,1) = 4; - m(3,2) = 5; - m(3,3) = -6; - m(4,0) = 7; - m(4,1) = -8; - m(4,2) = 9; - m(4,3) = 10; - - arrayslice2 += m; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || - arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || - mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 2 0 0 )\n" - " ( -4 0 -6 0 )\n" - " ( 0 8 10 -12 )\n" - " ( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array addition assignment (unaligned/unpadded)"; - - using blaze::unaligned; - using blaze::unpadded; - using blaze::rowMajor; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - using UnalignedUnpadded = blaze::CustomMatrix; - std::unique_ptr memory( new int[21] ); - UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); - m(0,0) = 0; - m(0,1) = 0; - m(0,2) = 0; - m(0,3) = 0; - m(1,0) = 0; - m(1,1) = 1; - m(1,2) = 0; - m(1,3) = 0; - m(2,0) = -2; - m(2,1) = 0; - m(2,2) = -3; - m(2,3) = 0; - m(3,0) = 0; - m(3,1) = 4; - m(3,2) = 5; - m(3,3) = -6; - m(4,0) = 7; - m(4,1) = -8; - m(4,2) = 9; - m(4,3) = 10; - - arrayslice2 += m; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 2 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -4 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -6 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 8 || arrayslice2(3,2) != 10 || arrayslice2(3,3) != -12 || - arrayslice2(4,0) != 14 || arrayslice2(4,1) != -16 || arrayslice2(4,2) != 18 || arrayslice2(4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 2 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -4 || mat_(1,2,1) != 0 || mat_(1,2,2) != -6 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 8 || mat_(1,3,2) != 10 || mat_(1,3,3) != -12 || - mat_(1,4,0) != 14 || mat_(1,4,1) != -16 || mat_(1,4,2) != 18 || mat_(1,4,3) != 20 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 2 0 0 )\n" - " ( -4 0 -6 0 )\n" - " ( 0 8 10 -12 )\n" - " ( 14 -16 18 20 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice subtraction assignment operators. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the subtraction assignment operators of the ArraySlice -// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testSubAssign() -{ - //===================================================================================== - // ArraySlice subtraction assignment - //===================================================================================== - - { - test_ = "ArraySlice subtraction assignment"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 -= blaze::arrayslice<2>( mat_, 0UL ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 0UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || - arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // dense array subtraction assignment - //===================================================================================== - - { - test_ = "dense array subtraction assignment (mixed type)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - const blaze::DynamicMatrix vec{{0, 0, 0, 0}, - {0, 1, 0, 0}, - {-2, 0, -3, 0}, - {0, 4, 5, -6}, - {7, -8, 9, 10}}; - - arrayslice2 -= vec; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 0UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || - arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - } - } - - { - test_ = "dense array subtraction assignment (aligned/padded)"; - - using blaze::aligned; - using blaze::padded; - using blaze::rowMajor; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - using AlignedPadded = blaze::CustomMatrix; - std::unique_ptr memory( blaze::allocate( 80UL ) ); - AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); - m(0,0) = 0; - m(0,1) = 0; - m(0,2) = 0; - m(0,3) = 0; - m(1,0) = 0; - m(1,1) = 1; - m(1,2) = 0; - m(1,3) = 0; - m(2,0) = -2; - m(2,1) = 0; - m(2,2) = -3; - m(2,3) = 0; - m(3,0) = 0; - m(3,1) = 4; - m(3,2) = 5; - m(3,3) = -6; - m(4,0) = 7; - m(4,1) = -8; - m(4,2) = 9; - m(4,3) = 10; - - arrayslice2 -= m; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 0UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || - arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array subtraction assignment (unaligned/unpadded)"; - - using blaze::unaligned; - using blaze::unpadded; - using blaze::rowMajor; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - using UnalignedUnpadded = blaze::CustomMatrix; - std::unique_ptr memory( new int[21] ); - UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); - m(0,0) = 0; - m(0,1) = 0; - m(0,2) = 0; - m(0,3) = 0; - m(1,0) = 0; - m(1,1) = 1; - m(1,2) = 0; - m(1,3) = 0; - m(2,0) = -2; - m(2,1) = 0; - m(2,2) = -3; - m(2,3) = 0; - m(3,0) = 0; - m(3,1) = 4; - m(3,2) = 5; - m(3,3) = -6; - m(4,0) = 7; - m(4,1) = -8; - m(4,2) = 9; - m(4,3) = 10; - - arrayslice2 -= m; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 0UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || - arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice multiplication assignment operators. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the multiplication assignment operators of the ArraySlice -// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testMultAssign() -{ - //===================================================================================== - // ArraySlice multiplication assignment - //===================================================================================== - - { - test_ = "ArraySlice multiplication assignment"; - - initialize(); - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - arrayslice2 *= blaze::arrayslice<2>( m, 0UL ); - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || - arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || - arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || - m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || - m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 90 114 138 )\n" - " ( 54 69 84 )\n" - " ( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // dense array multiplication assignment - //===================================================================================== - - { - test_ = "dense array multiplication assignment (mixed type)"; - - initialize(); - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - - const blaze::DynamicMatrix m1{ - {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; - - arrayslice2 *= m1; - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || - arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || - arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || - m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || - m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 90 114 138 )\n" - " ( 54 69 84 )\n" - " ( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array multiplication assignment (aligned/padded)"; - - using blaze::aligned; - using blaze::padded; - using blaze::rowMajor; - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - - using AlignedPadded = blaze::CustomMatrix; - std::unique_ptr memory( blaze::allocate( 48UL ) ); - AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); - m1(0,0) = 1; - m1(0,1) = 2; - m1(0,2) = 3; - m1(1,0) = 4; - m1(1,1) = 5; - m1(1,2) = 6; - m1(2,0) = 7; - m1(2,1) = 8; - m1(2,2) = 9; - - arrayslice2 *= m1; - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || - arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || - arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || - m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || - m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 90 114 138 )\n" - " ( 54 69 84 )\n" - " ( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array multiplication assignment (unaligned/unpadded)"; - - using blaze::unaligned; - using blaze::unpadded; - using blaze::rowMajor; - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - - using UnalignedUnpadded = blaze::CustomMatrix; - std::unique_ptr memory( new int[10] ); - UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); - m1(0,0) = 1; - m1(0,1) = 2; - m1(0,2) = 3; - m1(1,0) = 4; - m1(1,1) = 5; - m1(1,2) = 6; - m1(2,0) = 7; - m1(2,1) = 8; - m1(2,2) = 9; - - arrayslice2 *= m1; - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 90 || arrayslice2(0,1) != 114 || arrayslice2(0,2) != 138 || - arrayslice2(1,0) != 54 || arrayslice2(1,1) != 69 || arrayslice2(1,2) != 84 || - arrayslice2(2,0) != 18 || arrayslice2(2,1) != 24 || arrayslice2(2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || - m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || - m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 90 114 138 )\n" - " ( 54 69 84 )\n" - " ( 18 24 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice Schur product assignment operators. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the Schur product assignment operators of the ArraySlice -// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testSchurAssign() -{ - //===================================================================================== - // ArraySlice Schur product assignment - //===================================================================================== - - { - test_ = "ArraySlice Schur product assignment"; - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - arrayslice2 %= blaze::arrayslice<2>( m, 0UL ); - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || - arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || - arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || - m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || - m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 9 16 21 )\n" - " ( 24 25 24 )\n" - " ( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // dense array Schur product assignment - //===================================================================================== - - { - test_ = "dense vector Schur product assignment (mixed type)"; - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - - const blaze::DynamicMatrix m1{ - {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; - - arrayslice2 %= m1; - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || - arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || - arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || - m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || - m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 9 16 21 )\n" - " ( 24 25 24 )\n" - " ( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array Schur product assignment (aligned/padded)"; - - using blaze::aligned; - using blaze::padded; - using blaze::rowMajor; - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - - using AlignedPadded = blaze::CustomMatrix; - std::unique_ptr memory( blaze::allocate( 48UL ) ); - AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); - m1(0,0) = 1; - m1(0,1) = 2; - m1(0,2) = 3; - m1(1,0) = 4; - m1(1,1) = 5; - m1(1,2) = 6; - m1(2,0) = 7; - m1(2,1) = 8; - m1(2,2) = 9; - - arrayslice2 %= m1; - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || - arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || - arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || - m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || - m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 9 16 21 )\n" - " ( 24 25 24 )\n" - " ( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - { - test_ = "dense array Schur product assignment (unaligned/unpadded)"; - - using blaze::unaligned; - using blaze::unpadded; - using blaze::rowMajor; - - blaze::DynamicArray< 3, int > m{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, - {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}; - - RT arrayslice2 = blaze::arrayslice<2>( m, 1UL ); - - using UnalignedUnpadded = blaze::CustomMatrix; - std::unique_ptr memory( new int[10] ); - UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); - m1(0,0) = 1; - m1(0,1) = 2; - m1(0,2) = 3; - m1(1,0) = 4; - m1(1,1) = 5; - m1(1,2) = 6; - m1(2,0) = 7; - m1(2,1) = 8; - m1(2,2) = 9; - - arrayslice2 %= m1; - - checkRows ( arrayslice2, 3UL ); - checkColumns ( arrayslice2, 3UL ); - checkCapacity( arrayslice2, 9UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( m, 3UL ); - checkColumns ( m, 3UL ); - checkPages ( m, 2UL ); - checkNonZeros( m, 18UL ); - - if( arrayslice2(0,0) != 9 || arrayslice2(0,1) != 16 || arrayslice2(0,2) != 21 || - arrayslice2(1,0) != 24 || arrayslice2(1,1) != 25 || arrayslice2(1,2) != 24 || - arrayslice2(2,0) != 21 || arrayslice2(2,1) != 16 || arrayslice2(2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || - m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || - m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || - m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || - m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || - m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 1 2 3 )\n" - " ( 4 5 6 )\n" - " ( 7 8 9 ))\n" - "(( 9 16 21 )\n" - " ( 24 25 24 )\n" - " ( 21 16 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of all ArraySlice (self-)scaling operations. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of all available ways to scale an instance of the ArraySlice -// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testScaling() -{ - //===================================================================================== - // self-scaling (v*=2) - //===================================================================================== - - { - test_ = "self-scaling (v*=2)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 *= 3; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || - arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || - mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 3 0 0 )\n" - " ( -6 0 -9 0 )\n" - " ( 0 12 15 -18 )\n" - " ( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // self-scaling (v=v*2) - //===================================================================================== - - { - test_ = "self-scaling (v=v*3)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 = arrayslice2 * 3; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || - arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || - mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 3 0 0 )\n" - " ( -6 0 -9 0 )\n" - " ( 0 12 15 -18 )\n" - " ( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // self-scaling (v=3*v) - //===================================================================================== - - { - test_ = "self-scaling (v=3*v)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 = 3 * arrayslice2; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || - arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || - mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 3 0 0 )\n" - " ( -6 0 -9 0 )\n" - " ( 0 12 15 -18 )\n" - " ( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // self-scaling (v/=s) - //===================================================================================== - - { - test_ = "self-scaling (v/=s)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 /= (1.0/3.0); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || - arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || - mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 3 0 0 )\n" - " ( -6 0 -9 0 )\n" - " ( 0 12 15 -18 )\n" - " ( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // self-scaling (v=v/s) - //===================================================================================== - - { - test_ = "self-scaling (v=v/s)"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2 = arrayslice2 / (1.0/3.0); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || - arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || - mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 3 0 0 )\n" - " ( -6 0 -9 0 )\n" - " ( 0 12 15 -18 )\n" - " ( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - - //===================================================================================== - // ArraySlice::scale() - //===================================================================================== - - { - test_ = "ArraySlice::scale()"; - - initialize(); - - // Integral scaling the 3rd arrayslice - { - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2.scale( 3 ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 3 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -6 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -9 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 12 || arrayslice2(3,2) != 15 || arrayslice2(3,3) != -18 || - arrayslice2(4,0) != 21 || arrayslice2(4,1) != -24 || arrayslice2(4,2) != 27 || arrayslice2(4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 3 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -6 || mat_(1,2,1) != 0 || mat_(1,2,2) != -9 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 12 || mat_(1,3,2) != 15 || mat_(1,3,3) != -18 || - mat_(1,4,0) != 21 || mat_(1,4,1) != -24 || mat_(1,4,2) != 27 || mat_(1,4,3) != 30 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 3 0 0 )\n" - " ( -6 0 -9 0 )\n" - " ( 0 12 15 -18 )\n" - " ( 21 -24 27 30 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - initialize(); - - // Floating point scaling the 3rd arrayslice - { - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - arrayslice2.scale( 0.5 ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 19UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -1 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -1 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 2 || arrayslice2(3,2) != 2 || arrayslice2(3,3) != -3 || - arrayslice2(4,0) != 3 || arrayslice2(4,1) != -4 || arrayslice2(4,2) != 4 || arrayslice2(4,3) != 5 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( -1 0 -1 0 )\n( 0 12 2 -3 )\n( 3 -4 4 5 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -1 || mat_(1,2,1) != 0 || mat_(1,2,2) != -1 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 2 || mat_(1,3,2) != 2 || mat_(1,3,3) != -3 || - mat_(1,4,0) != 3 || mat_(1,4,1) != -4 || mat_(1,4,2) != 4 || mat_(1,4,3) != 5 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed self-scaling operation\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( -1 0 -1 0 )\n" - " ( 0 2 2 -3 )\n" - " ( 3 -4 4 5 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice function call operator. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of adding and accessing elements via the function call operator -// of the ArraySlice specialization. In case an error is detected, a \a std::runtime_error exception -// is thrown. -*/ -void DenseGeneralTest::testFunctionCall() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "ArraySlice::operator()"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - // Assignment to the element at index (0,1) - arrayslice2(0,1) = 9; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 11UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 21UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 9 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Assignment to the element at index (2,2) - arrayslice2(2,2) = 0; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 9 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Assignment to the element at index (4,1) - arrayslice2(4,1) = -9; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 9 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Addition assignment to the element at index (0,1) - arrayslice2(0,1) += -3; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Subtraction assignment to the element at index (2,0) - arrayslice2(2,0) -= 6; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -8 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -8 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Multiplication assignment to the element at index (4,0) - arrayslice2(4,0) *= -3; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -8 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != -21 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -8 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Division assignment to the element at index (3,3) - arrayslice2(3,3) /= 2; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 6 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -8 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -3 || - arrayslice2(4,0) != -21 || arrayslice2(4,1) != -9 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -3 || - mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -8 0 0 0 )\n" - " ( 0 4 5 -3 )\n" - " ( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice at() operator. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of adding and accessing elements via the at() operator -// of the ArraySlice specialization. In case an error is detected, a \a std::runtime_error exception -// is thrown. -*/ -void DenseGeneralTest::testAt() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "ArraySlice::at()"; - - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - // Assignment to the element at index (0,1) - arrayslice2.at(0,1) = 9; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 11UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 21UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 9 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != -3 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || - arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -8 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Assignment to the element at index (2,2) - arrayslice2.at(2,2) = 0; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 9 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || - arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -8 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -8 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Assignment to the element at index (4,1) - arrayslice2.at(4,1) = -9; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 9 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || - arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 9 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 9 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Addition assignment to the element at index (0,1) - arrayslice2.at(0,1) += -3; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -2 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || - arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Subtraction assignment to the element at index (2,0) - arrayslice2.at(2,0) -= 6; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -8 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || - arrayslice2.at(4,0) != 7 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 7 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -8 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Multiplication assignment to the element at index (4,0) - arrayslice2.at(4,0) *= -3; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -8 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -6 || - arrayslice2.at(4,0) != -21 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -8 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Division assignment to the element at index (3,3) - arrayslice2.at(3,3) /= 2; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2.at(0,0) != 0 || arrayslice2.at(0,1) != 6 || arrayslice2.at(0,2) != 0 || arrayslice2.at(0,3) != 0 || - arrayslice2.at(1,0) != 0 || arrayslice2.at(1,1) != 1 || arrayslice2.at(1,2) != 0 || arrayslice2.at(1,3) != 0 || - arrayslice2.at(2,0) != -8 || arrayslice2.at(2,1) != 0 || arrayslice2.at(2,2) != 0 || arrayslice2.at(2,3) != 0 || - arrayslice2.at(3,0) != 0 || arrayslice2.at(3,1) != 4 || arrayslice2.at(3,2) != 5 || arrayslice2.at(3,3) != -3 || - arrayslice2.at(4,0) != -21 || arrayslice2.at(4,1) != -9 || arrayslice2.at(4,2) != 9 || arrayslice2.at(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 6 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -8 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -3 || - mat_(1,4,0) != -21 || mat_(1,4,1) != -9 || mat_(1,4,2) != 9 || mat_(1,4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: At() failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 6 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -8 0 0 0 )\n" - " ( 0 4 5 -3 )\n" - " ( -21 -9 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the ArraySlice iterator implementation. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the iterator implementation of the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testIterator() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - initialize(); - - // Testing the Iterator default constructor - { - test_ = "Iterator default constructor"; - - RT::Iterator it{}; - - if( it != RT::Iterator() ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed iterator default constructor\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing the ConstIterator default constructor - { - test_ = "ConstIterator default constructor"; - - RT::ConstIterator it{}; - - if( it != RT::ConstIterator() ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed iterator default constructor\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing conversion from Iterator to ConstIterator - { - test_ = "Iterator/ConstIterator conversion"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - RT::ConstIterator it( begin( arrayslice2, 2UL ) ); - - if( it == end( arrayslice2, 2UL ) || *it != -2 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Failed iterator conversion detected\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Counting the number of elements in 1st arrayslice via Iterator (end-begin) - { - test_ = "Iterator subtraction (end-begin)"; - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - const ptrdiff_t number( end( arrayslice1, 2UL ) - begin( arrayslice1, 2UL ) ); - - if( number != 4L ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of elements detected\n" - << " Details:\n" - << " Number of elements : " << number << "\n" - << " Expected number of elements: 4\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Counting the number of elements in 1st arrayslice via Iterator (begin-end) - { - test_ = "Iterator subtraction (begin-end)"; - - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - const ptrdiff_t number( begin( arrayslice1, 2UL ) - end( arrayslice1, 2UL ) ); - - if( number != -4L ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of elements detected\n" - << " Details:\n" - << " Number of elements : " << number << "\n" - << " Expected number of elements: -4\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Counting the number of elements in 2nd arrayslice via ConstIterator (end-begin) - { - test_ = "ConstIterator subtraction (end-begin)"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - const ptrdiff_t number( cend( arrayslice2, 2UL ) - cbegin( arrayslice2, 2UL ) ); - - if( number != 4L ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of elements detected\n" - << " Details:\n" - << " Number of elements : " << number << "\n" - << " Expected number of elements: 4\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Counting the number of elements in 2nd arrayslice via ConstIterator (begin-end) - { - test_ = "ConstIterator subtraction (begin-end)"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - const ptrdiff_t number( cbegin( arrayslice2, 2UL ) - cend( arrayslice2, 2UL ) ); - - if( number != -4L ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid number of elements detected\n" - << " Details:\n" - << " Number of elements : " << number << "\n" - << " Expected number of elements: -4\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing read-only access via ConstIterator - { - test_ = "read-only access via ConstIterator"; - - RT arrayslice3 = blaze::arrayslice<2>( mat_, 0UL ); - RT::ConstIterator it ( cbegin( arrayslice3, 4UL ) ); - RT::ConstIterator end( cend( arrayslice3, 4UL ) ); - - if( it == end || *it != 7 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid initial iterator detected\n"; - throw std::runtime_error( oss.str() ); - } - - ++it; - - if( it == end || *it != -8 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator pre-increment failed\n"; - throw std::runtime_error( oss.str() ); - } - - --it; - - if( it == end || *it != 7 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator pre-decrement failed\n"; - throw std::runtime_error( oss.str() ); - } - - it++; - - if( it == end || *it != -8 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator post-increment failed\n"; - throw std::runtime_error( oss.str() ); - } - - it--; - - if( it == end || *it != 7 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator post-decrement failed\n"; - throw std::runtime_error( oss.str() ); - } - - it += 2UL; - - if( it == end || *it != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator addition assignment failed\n"; - throw std::runtime_error( oss.str() ); - } - - it -= 2UL; - - if( it == end || *it != 7 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator subtraction assignment failed\n"; - throw std::runtime_error( oss.str() ); - } - - it = it + 3UL; - - if( it == end || *it != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator/scalar addition failed\n"; - throw std::runtime_error( oss.str() ); - } - - it = it - 3UL; - - if( it == end || *it != 7 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator/scalar subtraction failed\n"; - throw std::runtime_error( oss.str() ); - } - - it = 4UL + it; - - if( it != end ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Scalar/iterator addition failed\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing assignment via Iterator - { - test_ = "assignment via Iterator"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - int value = 6; - - for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { - *it = value++; - } - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 6 || arrayslice2(4,1) != 7 || arrayslice2(4,2) != 8 || arrayslice2(4,3) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 6 || mat_(1,4,1) != 7 || mat_(1,4,2) != 8 || mat_(1,4,3) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 6 7 8 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing addition assignment via Iterator - { - test_ = "addition assignment via Iterator"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - int value = 2; - - for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { - *it += value++; - } - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 8 || arrayslice2(4,1) != 10 || arrayslice2(4,2) != 12 || arrayslice2(4,3) != 14 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 8 10 12 14 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 8 || mat_(1,4,1) != 10 || mat_(1,4,2) != 12 || mat_(1,4,3) != 14 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Addition assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 8 10 12 14 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing subtraction assignment via Iterator - { - test_ = "subtraction assignment via Iterator"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - int value = 2; - - for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { - *it -= value++; - } - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 6 || arrayslice2(4,1) != 7 || arrayslice2(4,2) != 8 || arrayslice2(4,3) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 6 || mat_(1,4,1) != 7 || mat_(1,4,2) != 8 || mat_(1,4,3) != 9 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subtraction assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 6 7 8 9 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing multiplication assignment via Iterator - { - test_ = "multiplication assignment via Iterator"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - int value = 1; - - for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { - *it *= value++; - } - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 6 || arrayslice2(4,1) != 14 || arrayslice2(4,2) != 24 || arrayslice2(4,3) != 36 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 14 24 36 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 6 || mat_(1,4,1) != 14 || mat_(1,4,2) != 24 || mat_(1,4,3) != 36 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Multiplication assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 6 14 24 36 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Testing division assignment via Iterator - { - test_ = "division assignment via Iterator"; - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - for( RT::Iterator it=begin( arrayslice2, 4UL ); it!=end( arrayslice2, 4UL ); ++it ) { - *it /= 2; - } - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 3 || arrayslice2(4,1) != 7 || arrayslice2(4,2) != 12 || arrayslice2(4,3) != 18 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Division assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 3 7 12 18 ))\n"; - throw std::runtime_error( oss.str() ); - } - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 1 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != -2 || mat_(1,2,1) != 0 || mat_(1,2,2) != -3 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 4 || mat_(1,3,2) != 5 || mat_(1,3,3) != -6 || - mat_(1,4,0) != 3 || mat_(1,4,1) != 7 || mat_(1,4,2) != 12 || mat_(1,4,3) != 18 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Division assignment via iterator failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 0 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 3 7 12 18 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c nonZeros() member function of the ArraySlice specialization. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c nonZeros() member function of the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testNonZeros() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "ArraySlice::nonZeros()"; - - initialize(); - - // Initialization check - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != -3 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Initialization failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Changing the number of non-zeros via the dense arrayslice - arrayslice2(2, 2) = 0; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 19UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - - // Changing the number of non-zeros via the dense array - mat_(1,3,0) = 5; - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 10UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 20UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 5 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Matrix function call operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 5 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c reset() member function of the ArraySlice specialization. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c reset() member function of the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testReset() -{ - using blaze::reset; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "ArraySlice::reset()"; - - // Resetting a single element in arrayslice 3 - { - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - reset( arrayslice2(2, 2) ); - - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 19UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Reset operator failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Resetting the 1st arrayslice (lvalue) - { - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - reset( arrayslice2 ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 0UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || - arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Reset operation of 1st arrayslice failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Resetting the 1st arrayslice (rvalue) - { - initialize(); - - reset( blaze::arrayslice<2>( mat_, 1UL ) ); - - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Reset operation of 1st arrayslice failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c clear() function with the ArraySlice specialization. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c clear() function with the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testClear() -{ - using blaze::clear; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "clear() function"; - - // Clearing a single element in arrayslice 1 - { - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - clear( arrayslice2(2, 2) ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 9UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 19UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 1 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != -2 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 4 || arrayslice2(3,2) != 5 || arrayslice2(3,3) != -6 || - arrayslice2(4,0) != 7 || arrayslice2(4,1) != -8 || arrayslice2(4,2) != 9 || arrayslice2(4,3) != 10 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Clear operation failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Clearing the 3rd arrayslice (lvalue) - { - initialize(); - - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - clear( arrayslice2 ); - - checkRows ( arrayslice2, 5UL ); - checkColumns ( arrayslice2, 4UL ); - checkCapacity( arrayslice2, 20UL ); - checkNonZeros( arrayslice2, 0UL ); - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( arrayslice2(0,0) != 0 || arrayslice2(0,1) != 0 || arrayslice2(0,2) != 0 || arrayslice2(0,3) != 0 || - arrayslice2(1,0) != 0 || arrayslice2(1,1) != 0 || arrayslice2(1,2) != 0 || arrayslice2(1,3) != 0 || - arrayslice2(2,0) != 0 || arrayslice2(2,1) != 0 || arrayslice2(2,2) != 0 || arrayslice2(2,3) != 0 || - arrayslice2(3,0) != 0 || arrayslice2(3,1) != 0 || arrayslice2(3,2) != 0 || arrayslice2(3,3) != 0 || - arrayslice2(4,0) != 0 || arrayslice2(4,1) != 0 || arrayslice2(4,2) != 0 || arrayslice2(4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Clear operation of 3rd arrayslice failed\n" - << " Details:\n" - << " Result:\n" << arrayslice2 << "\n" - << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - - // Clearing the 4th arrayslice (rvalue) - { - initialize(); - - clear( blaze::arrayslice<2>( mat_, 1UL ) ); - - checkRows ( mat_, 5UL ); - checkColumns ( mat_, 4UL ); - checkPages ( mat_, 2UL ); - checkNonZeros( mat_, 10UL ); - - if( mat_(0,0,0) != 0 || mat_(0,0,1) != 0 || mat_(0,0,2) != 0 || mat_(0,0,3) != 0 || - mat_(0,1,0) != 0 || mat_(0,1,1) != 1 || mat_(0,1,2) != 0 || mat_(0,1,3) != 0 || - mat_(0,2,0) != -2 || mat_(0,2,1) != 0 || mat_(0,2,2) != -3 || mat_(0,2,3) != 0 || - mat_(0,3,0) != 0 || mat_(0,3,1) != 4 || mat_(0,3,2) != 5 || mat_(0,3,3) != -6 || - mat_(0,4,0) != 7 || mat_(0,4,1) != -8 || mat_(0,4,2) != 9 || mat_(0,4,3) != 10 || - mat_(1,0,0) != 0 || mat_(1,0,1) != 0 || mat_(1,0,2) != 0 || mat_(1,0,3) != 0 || - mat_(1,1,0) != 0 || mat_(1,1,1) != 0 || mat_(1,1,2) != 0 || mat_(1,1,3) != 0 || - mat_(1,2,0) != 0 || mat_(1,2,1) != 0 || mat_(1,2,2) != 0 || mat_(1,2,3) != 0 || - mat_(1,3,0) != 0 || mat_(1,3,1) != 0 || mat_(1,3,2) != 0 || mat_(1,3,3) != 0 || - mat_(1,4,0) != 0 || mat_(1,4,1) != 0 || mat_(1,4,2) != 0 || mat_(1,4,3) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Clear operation of 1st arrayslice failed\n" - << " Details:\n" - << " Result:\n" << mat_ << "\n" - << " Expected result:\n(( 0 0 0 0 )\n" - " ( 0 1 0 0 )\n" - " ( -2 0 -3 0 )\n" - " ( 0 4 5 -6 )\n" - " ( 7 -8 9 10 ))\n" - "(( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 )\n" - " ( 0 0 0 0 ))\n"; - throw std::runtime_error( oss.str() ); - } - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c isDefault() function with the ArraySlice specialization. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c isDefault() function with the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testIsDefault() -{ - using blaze::isDefault; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "isDefault() function"; - - initialize(); - - // isDefault with default arrayslice - { - RT arrayslice0 = blaze::arrayslice<2>( mat_, 0UL ); - arrayslice0 = 0; - - if( isDefault( arrayslice0(0, 0) ) != true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isDefault evaluation\n" - << " Details:\n" - << " ArraySlice element: " << arrayslice0(0, 0) << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( isDefault( arrayslice0 ) != true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isDefault evaluation\n" - << " Details:\n" - << " ArraySlice:\n" << arrayslice0 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isDefault with non-default arrayslice - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - - if( isDefault( arrayslice1(1, 1) ) != false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isDefault evaluation\n" - << " Details:\n" - << " ArraySlice element: " << arrayslice1(1, 1) << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( isDefault( arrayslice1 ) != false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isDefault evaluation\n" - << " Details:\n" - << " ArraySlice:\n" << arrayslice1 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c isSame() function with the ArraySlice specialization. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c isSame() function with the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testIsSame() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "isSame() function"; - - // isSame with matching arrayslices - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 0UL ); - RT arrayslice2 = blaze::arrayslice<2>( mat_, 1UL ); - - arrayslice1 = 42; - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with arrayslice and matching submatrix - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto sv = blaze::submatrix( arrayslice1, 0UL, 0UL, 5UL, 4UL ); - - if( blaze::isSame( arrayslice1, sv ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " Dense arrayslice:\n" << arrayslice1 << "\n" - << " Dense submatrix:\n" << sv << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( sv, arrayslice1 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " Dense arrayslice:\n" << arrayslice1 << "\n" - << " Dense submatrix:\n" << sv << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with arrayslice and non-matching submatrix (different size) - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto sv = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 3UL ); - - if( blaze::isSame( arrayslice1, sv ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " Dense arrayslice:\n" << arrayslice1 << "\n" - << " Dense submatrix:\n" << sv << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( sv, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " Dense arrayslice:\n" << arrayslice1 << "\n" - << " Dense submatrix:\n" << sv << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with arrayslice and non-matching submatrix (different offset) - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto sv = blaze::submatrix( arrayslice1, 1UL, 1UL, 3UL, 3UL ); - - if( blaze::isSame( arrayslice1, sv ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " Dense arrayslice:\n" << arrayslice1 << "\n" - << " Dense submatrix:\n" << sv << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( sv, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " Dense arrayslice:\n" << arrayslice1 << "\n" - << " Dense submatrix:\n" << sv << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with matching arrayslices on a common subtensor - { - auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm, 1UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices on a common subtensor - { - auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm, 0UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm, 1UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with matching subtensor on matrix and subtensor - { - auto sm = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm , 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices on tensor and subtensor (different arrayslice) - { - auto sm = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( mat_, 0UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm , 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices on tensor and subtensor (different size) - { - auto sm = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 4UL, 3UL ); - auto arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm , 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with matching arrayslices on two subtensors - { - auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices on two subtensors (different arrayslice) - { - auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 0UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices on two subtensors (different size) - { - auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 4UL, 3UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslices on two subtensors (different offset) - { - auto sm1 = blaze::subtensor( mat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 4UL, 2UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - - if( blaze::isSame( arrayslice1, arrayslice2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( blaze::isSame( arrayslice2, arrayslice1 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First arrayslice:\n" << arrayslice1 << "\n" - << " Second arrayslice:\n" << arrayslice2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with matching arrayslice submatrices on a subtensor - { - auto sm = blaze::subtensor( mat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); - auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); - auto sv2 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); - - if( blaze::isSame( sv1, sv2 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First submatrix:\n" << sv1 << "\n" - << " Second submatrix:\n" << sv2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslice subtensors on a submatrix (different size) - { - auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); - auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); - auto sv2 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 2UL ); - - if( blaze::isSame( sv1, sv2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First submatrix:\n" << sv1 << "\n" - << " Second submatrix:\n" << sv2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslice subtensors on a submatrix (different offset) - { - auto sm = blaze::subtensor( mat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm, 1UL ); - auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 1UL ); - auto sv2 = blaze::submatrix( arrayslice1, 0UL, 1UL, 2UL, 1UL ); - - if( blaze::isSame( sv1, sv2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First submatrix:\n" << sv1 << "\n" - << " Second submatrix:\n" << sv2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with matching arrayslice subtensors on two subtensors - { - auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 2UL ); - auto sv2 = blaze::submatrix( arrayslice2, 0UL, 0UL, 3UL, 2UL ); - - if( blaze::isSame( sv1, sv2 ) == false ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First submatrix:\n" << sv1 << "\n" - << " Second submatrix:\n" << sv2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslice subtensors on two subtensors (different size) - { - auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 2UL ); - auto sv2 = blaze::submatrix( arrayslice2, 0UL, 0UL, 2UL, 2UL ); - - if( blaze::isSame( sv1, sv2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First submatrix:\n" << sv1 << "\n" - << " Second submatrix:\n" << sv2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - // isSame with non-matching arrayslice subtensors on two subtensors (different offset) - { - auto sm1 = blaze::subtensor( mat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); - auto sm2 = blaze::subtensor( mat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); - auto arrayslice1 = blaze::arrayslice<2>( sm1, 1UL ); - auto arrayslice2 = blaze::arrayslice<2>( sm2, 0UL ); - auto sv1 = blaze::submatrix( arrayslice1, 0UL, 0UL, 3UL, 2UL ); - auto sv2 = blaze::submatrix( arrayslice2, 0UL, 1UL, 3UL, 2UL ); - - if( blaze::isSame( sv1, sv2 ) == true ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Invalid isSame evaluation\n" - << " Details:\n" - << " First submatrix:\n" << sv1 << "\n" - << " Second submatrix:\n" << sv2 << "\n"; - throw std::runtime_error( oss.str() ); - } - } - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c submatrix() function with the ArraySlice specialization. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c submatrix() function used with the ArraySlice specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testSubmatrix() -{ - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "submatrix() function"; - - initialize(); - - { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto sm = blaze::submatrix( arrayslice1, 1UL, 1UL, 2UL, 3UL ); - - if( sm(0,0) != 1 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subscript operator access failed\n" - << " Details:\n" - << " Result: " << sm(0,0) << "\n" - << " Expected result: 1\n"; - throw std::runtime_error( oss.str() ); - } - - if( *sm.begin(1) != 0 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator access failed\n" - << " Details:\n" - << " Result: " << *sm.begin(1) << "\n" - << " Expected result: 0\n"; - throw std::runtime_error( oss.str() ); - } - } - - try { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto sm = blaze::submatrix( arrayslice1, 4UL, 0UL, 4UL, 4UL ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds submatrix succeeded\n" - << " Details:\n" - << " Result:\n" << sm << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - - try { - RT arrayslice1 = blaze::arrayslice<2>( mat_, 1UL ); - auto sm = blaze::submatrix( arrayslice1, 0UL, 0UL, 2UL, 6UL ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds submatrix succeeded\n" - << " Details:\n" - << " Result:\n" << sm << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - -//************************************************************************************************* -/*!\brief Test of the \c row() function with the Submatrix class template. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c row() function with the Submatrix specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testRow() -{ - using blaze::arrayslice; - using blaze::row; - using blaze::aligned; - using blaze::unaligned; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "Pageslice row() function"; - - initialize(); - - { - RT arrayslice1 = arrayslice( mat_, 0UL ); - RT arrayslice2 = arrayslice( mat_, 1UL ); - auto row1 = row( arrayslice1, 1UL ); - auto row2 = row( arrayslice2, 1UL ); - - if( row1 != row2 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Row function failed\n" - << " Details:\n" - << " Result:\n" << row1 << "\n" - << " Expected result:\n" << row2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( row1[1] != row2[1] ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subscript operator access failed\n" - << " Details:\n" - << " Result: " << row1[1] << "\n" - << " Expected result: " << row2[1] << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( *row1.begin() != *row2.begin() ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator access failed\n" - << " Details:\n" - << " Result: " << *row1.begin() << "\n" - << " Expected result: " << *row2.begin() << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - try { - RT arrayslice1 = arrayslice( mat_, 0UL ); - auto row8 = row( arrayslice1, 8UL ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds row succeeded\n" - << " Details:\n" - << " Result:\n" << row8 << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c rows() function with the Submatrix class template. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c rows() function with the Submatrix specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testRows() -{ - using blaze::arrayslice; - using blaze::rows; - using blaze::aligned; - using blaze::unaligned; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "Pageslice rows() function"; - - initialize(); - - { - RT arrayslice1 = arrayslice( mat_, 0UL ); - RT arrayslice2 = arrayslice( mat_, 1UL ); - auto rs1 = rows( arrayslice1, { 0UL, 2UL, 4UL, 3UL } ); - auto rs2 = rows( arrayslice2, { 0UL, 2UL, 4UL, 3UL } ); - - if( rs1 != rs2 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Rows function failed\n" - << " Details:\n" - << " Result:\n" << rs1 << "\n" - << " Expected result:\n" << rs2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( rs1(1,1) != rs2(1,1) ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator access failed\n" - << " Details:\n" - << " Result: " << rs1(1,1) << "\n" - << " Expected result: " << rs2(1,1) << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( *rs1.begin( 1UL ) != *rs2.begin( 1UL ) ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator access failed\n" - << " Details:\n" - << " Result: " << *rs1.begin( 1UL ) << "\n" - << " Expected result: " << *rs2.begin( 1UL ) << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - try { - RT arrayslice1 = arrayslice( mat_, 1UL ); - auto rs = rows( arrayslice1, { 8UL } ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds row selection succeeded\n" - << " Details:\n" - << " Result:\n" << rs << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c column() function with the Submatrix class template. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c column() function with the Submatrix specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testColumn() -{ - using blaze::arrayslice; - using blaze::column; - using blaze::aligned; - using blaze::unaligned; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "Pageslice column() function"; - - initialize(); - - { - RT arrayslice1 = arrayslice( mat_, 0UL ); - RT arrayslice2 = arrayslice( mat_, 1UL ); - auto col1 = column( arrayslice1, 1UL ); - auto col2 = column( arrayslice2, 1UL ); - - if( col1 != col2 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Column function failed\n" - << " Details:\n" - << " Result:\n" << col1 << "\n" - << " Expected result:\n" << col2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( col1[1] != col2[1] ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subscript operator access failed\n" - << " Details:\n" - << " Result: " << col1[1] << "\n" - << " Expected result: " << col2[1] << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( *col1.begin() != *col2.begin() ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator access failed\n" - << " Details:\n" - << " Result: " << *col1.begin() << "\n" - << " Expected result: " << *col2.begin() << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - try { - RT arrayslice1 = arrayslice( mat_, 0UL ); - auto col16 = column( arrayslice1, 16UL ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds column succeeded\n" - << " Details:\n" - << " Result:\n" << col16 << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c columns() function with the Submatrix class template. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c columns() function with the Submatrix specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testColumns() -{ - using blaze::arrayslice; - using blaze::rows; - using blaze::aligned; - using blaze::unaligned; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "columns() function"; - - initialize(); - - { - RT arrayslice1 = arrayslice( mat_, 0UL ); - RT arrayslice2 = arrayslice( mat_, 1UL ); - auto cs1 = columns( arrayslice1, { 0UL, 2UL, 2UL, 3UL } ); - auto cs2 = columns( arrayslice2, { 0UL, 2UL, 2UL, 3UL } ); - - if( cs1 != cs2 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Rows function failed\n" - << " Details:\n" - << " Result:\n" << cs1 << "\n" - << " Expected result:\n" << cs2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( cs1(1,1) != cs2(1,1) ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Function call operator access failed\n" - << " Details:\n" - << " Result: " << cs1(1,1) << "\n" - << " Expected result: " << cs2(1,1) << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( *cs1.begin( 1UL ) != *cs2.begin( 1UL ) ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator access failed\n" - << " Details:\n" - << " Result: " << *cs1.begin( 1UL ) << "\n" - << " Expected result: " << *cs2.begin( 1UL ) << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - try { - RT arrayslice1 = arrayslice( mat_, 1UL ); - auto cs = columns( arrayslice1, { 16UL } ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds column selection succeeded\n" - << " Details:\n" - << " Result:\n" << cs << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - - -//************************************************************************************************* -/*!\brief Test of the \c band() function with the Submatrix class template. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function performs a test of the \c band() function with the Submatrix specialization. -// In case an error is detected, a \a std::runtime_error exception is thrown. -*/ -void DenseGeneralTest::testBand() -{ - using blaze::arrayslice; - using blaze::band; - using blaze::aligned; - using blaze::unaligned; - - - //===================================================================================== - // matrix tests - //===================================================================================== - - { - test_ = "Pageslice band() function"; - - initialize(); - - { - RT arrayslice1 = arrayslice( mat_, 0UL ); - RT arrayslice2 = arrayslice( mat_, 1UL ); - auto b1 = band( arrayslice1, 1L ); - auto b2 = band( arrayslice2, 1L ); - - if( b1 != b2 ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Band function failed\n" - << " Details:\n" - << " Result:\n" << b1 << "\n" - << " Expected result:\n" << b2 << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( b1[1] != b2[1] ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Subscript operator access failed\n" - << " Details:\n" - << " Result: " << b1[1] << "\n" - << " Expected result: " << b2[1] << "\n"; - throw std::runtime_error( oss.str() ); - } - - if( *b1.begin() != *b2.begin() ) { - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Iterator access failed\n" - << " Details:\n" - << " Result: " << *b1.begin() << "\n" - << " Expected result: " << *b2.begin() << "\n"; - throw std::runtime_error( oss.str() ); - } - } - - try { - RT arrayslice1 = arrayslice( mat_, 1UL ); - auto b8 = band( arrayslice1, -8L ); - - std::ostringstream oss; - oss << " Test: " << test_ << "\n" - << " Error: Setup of out-of-bounds band succeeded\n" - << " Details:\n" - << " Result:\n" << b8 << "\n"; - throw std::runtime_error( oss.str() ); - } - catch( std::invalid_argument& ) {} - } -} -//************************************************************************************************* - - - -//================================================================================================= -// -// UTILITY FUNCTIONS -// -//================================================================================================= - -//************************************************************************************************* -/*!\brief Initialization of all member matrices. -// -// \return void -// \exception std::runtime_error Error detected. -// -// This function initializes all member matrices to specific predetermined values. -*/ -void DenseGeneralTest::initialize() -{ - // Initializing the arrayslice-major dynamic matrix - mat_.reset(); - mat_(0,1,1) = 1; - mat_(0,2,0) = -2; - mat_(0,2,2) = -3; - mat_(0,3,1) = 4; - mat_(0,3,2) = 5; - mat_(0,3,3) = -6; - mat_(0,4,0) = 7; - mat_(0,4,1) = -8; - mat_(0,4,2) = 9; - mat_(0,4,3) = 10; - mat_(1,1,1) = 1; - mat_(1,2,0) = -2; - mat_(1,2,2) = -3; - mat_(1,3,1) = 4; - mat_(1,3,2) = 5; - mat_(1,3,3) = -6; - mat_(1,4,0) = 7; - mat_(1,4,1) = -8; - mat_(1,4,2) = 9; - mat_(1,4,3) = 10; -} -//************************************************************************************************* - -} // namespace arrayslice - -} // namespace mathtest - -} // namespace blazetest - - - - -//================================================================================================= -// -// MAIN FUNCTION -// -//================================================================================================= - -#if defined(BLAZE_USE_HPX_THREADS) -#include -#endif - -//************************************************************************************************* -int main() -{ - std::cout << " Running ArraySlice dense general test..." << std::endl; - - try - { - RUN_PAGESLICE_DENSEGENERAL_TEST; - } - catch( std::exception& ex ) { - std::cerr << "\n\n ERROR DETECTED during ArraySlice dense general test:\n" - << ex.what() << "\n"; - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} -//************************************************************************************************* diff --git a/blazetest/src/mathtest/arrayslice/IncludeTest.cpp b/blazetest/src/mathtest/arrayslice/IncludeTest.cpp deleted file mode 100644 index 3f3b2af..0000000 --- a/blazetest/src/mathtest/arrayslice/IncludeTest.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//================================================================================================= -/*! -// \file src/mathtest/arrayslice/IncludeTest.cpp -// \brief Source file for the PageSlice include test -// -// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved -// -// This file is part of the Blaze library. You can redistribute it and/or modify it under -// the terms of the New (Revised) BSD License. Redistribution and use in source and binary -// forms, with or without modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// 3. Neither the names of the Blaze development group nor the names of its contributors -// may be used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -*/ -//================================================================================================= - - -//************************************************************************************************* -// Includes -//************************************************************************************************* - -#include - - - - -//================================================================================================= -// -// MAIN FUNCTION -// -//================================================================================================= - -#if defined(BLAZE_USE_HPX_THREADS) -#include -#endif - -//************************************************************************************************* -int main() -{ - return EXIT_SUCCESS; -} -//************************************************************************************************* diff --git a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp new file mode 100644 index 0000000..f42e1cb --- /dev/null +++ b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp @@ -0,0 +1,5222 @@ +//================================================================================================= +/*! +// \file src/mathtest/quatslice/DenseGeneralTest.cpp +// \brief Source file for the QuatSlice dense general test +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2019 Bita Hasheminezhad - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other quaterials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +namespace blazetest { + +namespace mathtest { + +namespace quatslice { + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constructor for the QuatSlice dense general test. +// +// \exception std::runtime_error Operation error detected. +*/ +DenseGeneralTest::DenseGeneralTest() + //: quat_ ( 3UL, 2UL, 5UL, 4UL ) +{ + testConstructors(); + //testAssignment(); + //testAddAssign(); + //testSubAssign(); + //testMultAssign(); + //testSchurAssign(); + //testScaling(); + //testFunctionCall(); + //testAt(); + //testIterator(); + //testNonZeros(); + //testReset(); + //testClear(); + //testIsDefault(); + //testIsSame(); + //testSubquaternion(); + //testRow(); + //testRows(); + //testColumn(); + //testColumns(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// TEST FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Test of the QuatSlice constructors. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all constructors of the QuatSlice specialization. In case an +// error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testConstructors() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + //{ + // test_ = "QuatSlice constructor (0x0)"; + + // AT quat; + + // // 0th quaternion quatslice + // try { + // blaze::quatslice( quat, 0UL ); + // } + // catch( std::invalid_argument& ) {} + //} + + //{ + // test_ = "QuatSlice constructor (2x0)"; + + // AT quat( 2UL, 2UL, 0UL ); + + // // 0th quaternion quatslice + // { + // RT quatslice0 = blaze::quatslice( quat, 0UL ); + + // checkRows ( quatslice0, 2UL ); + // checkColumns ( quatslice0, 0UL ); + // checkCapacity( quatslice0, 0UL ); + // checkNonZeros( quatslice0, 0UL ); + // } + + // // 1st quaternion quatslice + // { + // RT quatslice1 = blaze::quatslice( quat, 1UL ); + + // checkRows ( quatslice1, 2UL ); + // checkColumns ( quatslice1, 0UL ); + // checkCapacity( quatslice1, 0UL ); + // checkNonZeros( quatslice1, 0UL ); + // } + + // // 2nd quaternion quatslice + // try { + // blaze::quatslice( quat, 2UL ); + // } + // catch( std::invalid_argument& ) {} + //} + + //{ + // test_ = "QuatSlice constructor (5x4)"; + + // initialize(); + + // // 0th quaternion quatslice + // { + // RT quatslice0 = blaze::quatslice( quat_, 0UL ); + + // checkRows ( quatslice0, 5UL ); + // checkColumns ( quatslice0, 4UL ); + // checkCapacity( quatslice0, 20UL ); + // checkNonZeros( quatslice0, 10UL ); + + // if( quatslice0(0,0) != 0 || quatslice0(0,1) != 0 || quatslice0(0,2) != 0 || quatslice0(0,3) != 0 || + // quatslice0(1,0) != 0 || quatslice0(1,1) != 1 || quatslice0(1,2) != 0 || quatslice0(1,3) != 0 || + // quatslice0(2,0) != -2 || quatslice0(2,1) != 0 || quatslice0(2,2) != -3 || quatslice0(2,3) != 0 || + // quatslice0(3,0) != 0 || quatslice0(3,1) != 4 || quatslice0(3,2) != 5 || quatslice0(3,3) != -6 || + // quatslice0(4,0) != 7 || quatslice0(4,1) != -8 || quatslice0(4,2) != 9 || quatslice0(4,3) != 10 ) { + // std::ostringstream oss; + // oss << " Test: " << test_ << "\n" + // << " Error: Setup of 0th dense quatslice failed\n" + // << " Details:\n" + // << " Result:\n" << quatslice0 << "\n" + // << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + // throw std::runtime_error( oss.str() ); + // } + // } + + // // 1st quaternion quatslice + // { + // RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + // checkRows ( quatslice1, 5UL ); + // checkColumns ( quatslice1, 4UL ); + // checkCapacity( quatslice1, 20UL ); + // checkNonZeros( quatslice1, 10UL ); + + // if( quatslice1(0,0) != 0 || quatslice1(0,1) != 0 || quatslice1(0,2) != 0 || quatslice1(0,3) != 0 || + // quatslice1(1,0) != 0 || quatslice1(1,1) != 1 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || + // quatslice1(2,0) != -2 || quatslice1(2,1) != 0 || quatslice1(2,2) != -3 || quatslice1(2,3) != 0 || + // quatslice1(3,0) != 0 || quatslice1(3,1) != 4 || quatslice1(3,2) != 5 || quatslice1(3,3) != -6 || + // quatslice1(4,0) != 7 || quatslice1(4,1) != -8 || quatslice1(4,2) != 9 || quatslice1(4,3) != 10 ) { + // std::ostringstream oss; + // oss << " Test: " << test_ << "\n" + // << " Error: Setup of 1st dense quatslice failed\n" + // << " Details:\n" + // << " Result:\n" << quatslice1 << "\n" + // << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + // throw std::runtime_error( oss.str() ); + // } + // } + + // // 2nd quaternion quatslice + // try { + // RT quatslice2 = blaze::quatslice( quat_, 2UL ); + + // std::ostringstream oss; + // oss << " Test: " << test_ << "\n" + // << " Error: Out-of-bound quat access succeeded\n" + // << " Details:\n" + // << " Result:\n" << quatslice2 << "\n"; + // throw std::runtime_error( oss.str() ); + // } + // catch( std::invalid_argument& ) {} + //} +} +//************************************************************************************************* + +//************************************************************************************************* +/*!\brief Test of the QuatSlice assignment operators. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of all assignment operators of the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +//void DenseGeneralTest::testAssignment() +//{ +// //===================================================================================== +// // homogeneous assignment +// //===================================================================================== +// +// { +// test_ = "QuatSlice homogeneous assignment"; +// +// initialize(); +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// quatslice1 = 8; +// +// +// checkRows ( quatslice1, 5UL ); +// checkColumns ( quatslice1, 4UL ); +// checkCapacity( quatslice1, 20UL ); +// checkNonZeros( quatslice1, 20UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 30UL ); +// +// if( quatslice1(0,0) != 8 || quatslice1(0,1) != 8 || quatslice1(0,2) != 8 || quatslice1(0,3) != 8 || +// quatslice1(1,0) != 8 || quatslice1(1,1) != 8 || quatslice1(1,2) != 8 || quatslice1(1,3) != 8 || +// quatslice1(2,0) != 8 || quatslice1(2,1) != 8 || quatslice1(2,2) != 8 || quatslice1(2,3) != 8 || +// quatslice1(3,0) != 8 || quatslice1(3,1) != 8 || quatslice1(3,2) != 8 || quatslice1(3,3) != 8 || +// quatslice1(4,0) != 8 || quatslice1(4,1) != 8 || quatslice1(4,2) != 8 || quatslice1(4,3) != 8 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice1 << "\n" +// << " Expected result:\n(( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 8 || quat_(1,0,1) != 8 || quat_(1,0,2) != 8 || quat_(1,0,3) != 8 || +// quat_(1,1,0) != 8 || quat_(1,1,1) != 8 || quat_(1,1,2) != 8 || quat_(1,1,3) != 8 || +// quat_(1,2,0) != 8 || quat_(1,2,1) != 8 || quat_(1,2,2) != 8 || quat_(1,2,3) != 8 || +// quat_(1,3,0) != 8 || quat_(1,3,1) != 8 || quat_(1,3,2) != 8 || quat_(1,3,3) != 8 || +// quat_(1,4,0) != 8 || quat_(1,4,1) != 8 || quat_(1,4,2) != 8 || quat_(1,4,3) != 8 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 8 8 8 8 )\n" +// " ( 8 8 8 8 )\n" +// " ( 8 8 8 8 )\n" +// " ( 8 8 8 8 )\n" +// " ( 8 8 8 8 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // list assignment +// //===================================================================================== +// +// { +// test_ = "initializer list assignment (complete list)"; +// +// initialize(); +// +// RT quatslice3 = blaze::quatslice( quat_, 1UL ); +// quatslice3 = { +// {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} +// }; +// +// checkRows ( quatslice3, 5UL ); +// checkColumns ( quatslice3, 4UL ); +// checkCapacity( quatslice3, 20UL ); +// checkNonZeros( quatslice3, 20UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 30UL ); +// +// if( quatslice3(0,0) != 1 || quatslice3(0,1) != 2 || quatslice3(0,2) != 3 || quatslice3(0,3) != 4 || +// quatslice3(1,0) != 1 || quatslice3(1,1) != 2 || quatslice3(1,2) != 3 || quatslice3(1,3) != 4 || +// quatslice3(2,0) != 1 || quatslice3(2,1) != 2 || quatslice3(2,2) != 3 || quatslice3(2,3) != 4 || +// quatslice3(3,0) != 1 || quatslice3(3,1) != 2 || quatslice3(3,2) != 3 || quatslice3(3,3) != 4 || +// quatslice3(4,0) != 1 || quatslice3(4,1) != 2 || quatslice3(4,2) != 3 || quatslice3(4,3) != 4 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice3 << "\n" +// << " Expected result:\n(( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 1 || quat_(1,0,1) != 2 || quat_(1,0,2) != 3 || quat_(1,0,3) != 4 || +// quat_(1,1,0) != 1 || quat_(1,1,1) != 2 || quat_(1,1,2) != 3 || quat_(1,1,3) != 4 || +// quat_(1,2,0) != 1 || quat_(1,2,1) != 2 || quat_(1,2,2) != 3 || quat_(1,2,3) != 4 || +// quat_(1,3,0) != 1 || quat_(1,3,1) != 2 || quat_(1,3,2) != 3 || quat_(1,3,3) != 4 || +// quat_(1,4,0) != 1 || quat_(1,4,1) != 2 || quat_(1,4,2) != 3 || quat_(1,4,3) != 4 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 1 2 3 4 )\n" +// " ( 1 2 3 4 )\n" +// " ( 1 2 3 4 )\n" +// " ( 1 2 3 4 )\n" +// " ( 1 2 3 4 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "initializer list assignment (incomplete list)"; +// +// initialize(); +// +// RT quatslice3 = blaze::quatslice( quat_, 1UL ); +// quatslice3 = {{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}}; +// +// checkRows ( quatslice3, 5UL ); +// checkColumns ( quatslice3, 4UL ); +// checkCapacity( quatslice3, 20UL ); +// checkNonZeros( quatslice3, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice3(0,0) != 1 || quatslice3(0,1) != 2 || quatslice3(0,2) != 0 || quatslice3(0,3) != 0 || +// quatslice3(1,0) != 1 || quatslice3(1,1) != 2 || quatslice3(1,2) != 0 || quatslice3(1,3) != 0 || +// quatslice3(2,0) != 1 || quatslice3(2,1) != 2 || quatslice3(2,2) != 0 || quatslice3(2,3) != 0 || +// quatslice3(3,0) != 1 || quatslice3(3,1) != 2 || quatslice3(3,2) != 0 || quatslice3(3,3) != 0 || +// quatslice3(4,0) != 1 || quatslice3(4,1) != 2 || quatslice3(4,2) != 0 || quatslice3(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice3 << "\n" +// << " Expected result:\n(( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 1 || quat_(1,0,1) != 2 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 1 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 1 || quat_(1,2,1) != 2 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 1 || quat_(1,3,1) != 2 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 1 || quat_(1,4,1) != 2 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 1 2 0 0 )\n" +// " ( 1 2 0 0 )\n" +// " ( 1 2 0 0 )\n" +// " ( 1 2 0 0 )\n" +// " ( 1 2 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // copy assignment +// //===================================================================================== +// +// { +// test_ = "QuatSlice copy assignment"; +// +// initialize(); +// +// RT quatslice1 = blaze::quatslice( quat_, 0UL ); +// quatslice1 = 0; +// quatslice1 = blaze::quatslice( quat_, 1UL ); +// +// checkRows ( quatslice1, 5UL ); +// checkColumns ( quatslice1, 4UL ); +// checkCapacity( quatslice1, 20UL ); +// checkNonZeros( quatslice1, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 0 || quatslice1(0,2) != 0 || quatslice1(0,3) != 0 || +// quatslice1(1,0) != 0 || quatslice1(1,1) != 1 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || +// quatslice1(2,0) != -2 || quatslice1(2,1) != 0 || quatslice1(2,2) != -3 || quatslice1(2,3) != 0 || +// quatslice1(3,0) != 0 || quatslice1(3,1) != 4 || quatslice1(3,2) != 5 || quatslice1(3,3) != -6 || +// quatslice1(4,0) != 7 || quatslice1(4,1) != -8 || quatslice1(4,2) != 9 || quatslice1(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice1 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // dense quaternion assignment +// //===================================================================================== +// +// { +// test_ = "dense quaternion assignment (mixed type)"; +// +// initialize(); +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// +// blaze::DynamicMatrix m1; +// m1 = {{0, 8, 0, 9}, {0}, {0}, {0}, {0}}; +// +// quatslice1 = m1; +// +// checkRows ( quatslice1, 5UL ); +// checkColumns ( quatslice1, 4UL ); +// checkCapacity( quatslice1, 20UL ); +// checkNonZeros( quatslice1, 2UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 12UL ); +// +// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || +// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || +// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || +// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || +// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice1 << "\n" +// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 9 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion assignment (mixed type)"; +// +// initialize(); +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// +// blaze::DynamicMatrix m1; +// m1 = {{0, 8, 0, 9}, {0}, {0}, {0}, {0}}; +// +// quatslice1 = m1; +// +// checkRows ( quatslice1, 5UL ); +// checkColumns ( quatslice1, 4UL ); +// checkCapacity( quatslice1, 20UL ); +// checkNonZeros( quatslice1, 2UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 12UL ); +// +// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || +// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || +// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || +// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || +// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice1 << "\n" +// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 9 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion assignment (aligned/padded)"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// initialize(); +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// +// using AlignedPadded = blaze::CustomMatrix; +// std::unique_ptr memory( blaze::allocate( 80UL ) ); +// AlignedPadded m1( memory.get(), 5UL, 4UL, 16UL ); +// m1 = 0; +// m1(0,0) = 0; +// m1(0,1) = 8; +// m1(0,2) = 0; +// m1(0,3) = 9; +// +// quatslice1 = m1; +// +// checkRows ( quatslice1, 5UL ); +// checkColumns ( quatslice1, 4UL ); +// checkCapacity( quatslice1, 20UL ); +// checkNonZeros( quatslice1, 2UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 12UL ); +// +// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || +// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || +// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || +// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || +// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice1 << "\n" +// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 9 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion assignment (unaligned/unpadded)"; +// +// using blaze::unaligned; +// using blaze::unpadded; +// using blaze::rowMajor; +// +// initialize(); +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// +// using UnalignedUnpadded = blaze::CustomMatrix; +// std::unique_ptr memory( new int[21] ); +// UnalignedUnpadded m1( memory.get()+1UL, 5UL, 4UL ); +// m1 = 0; +// m1(0,0) = 0; +// m1(0,1) = 8; +// m1(0,2) = 0; +// m1(0,3) = 9; +// +// quatslice1 = m1; +// +// checkRows ( quatslice1, 5UL ); +// checkColumns ( quatslice1, 4UL ); +// checkCapacity( quatslice1, 20UL ); +// checkNonZeros( quatslice1, 2UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 12UL ); +// +// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || +// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || +// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || +// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || +// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice1 << "\n" +// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 9 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice addition assignment operators. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the addition assignment operators of the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testAddAssign() +//{ +// //===================================================================================== +// // QuatSlice addition assignment +// //===================================================================================== +// +// { +// test_ = "QuatSlice addition assignment"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 += blaze::quatslice( quat_, 0UL ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || +// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || +// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 2 0 0 )\n" +// " ( -4 0 -6 0 )\n" +// " ( 0 8 10 -12 )\n" +// " ( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // dense quaternion addition assignment +// //===================================================================================== +// +// { +// test_ = "dense quaternion addition assignment (mixed type)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// const blaze::DynamicMatrix vec{{0, 0, 0, 0}, +// {0, 1, 0, 0}, +// {-2, 0, -3, 0}, +// {0, 4, 5, -6}, +// {7, -8, 9, 10}}; +// +// quatslice2 += vec; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || +// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || +// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 2 0 0 )\n" +// " ( -4 0 -6 0 )\n" +// " ( 0 8 10 -12 )\n" +// " ( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion addition assignment (aligned/padded)"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// using AlignedPadded = blaze::CustomMatrix; +// std::unique_ptr memory( blaze::allocate( 80UL ) ); +// AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); +// m(0,0) = 0; +// m(0,1) = 0; +// m(0,2) = 0; +// m(0,3) = 0; +// m(1,0) = 0; +// m(1,1) = 1; +// m(1,2) = 0; +// m(1,3) = 0; +// m(2,0) = -2; +// m(2,1) = 0; +// m(2,2) = -3; +// m(2,3) = 0; +// m(3,0) = 0; +// m(3,1) = 4; +// m(3,2) = 5; +// m(3,3) = -6; +// m(4,0) = 7; +// m(4,1) = -8; +// m(4,2) = 9; +// m(4,3) = 10; +// +// quatslice2 += m; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || +// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || +// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 2 0 0 )\n" +// " ( -4 0 -6 0 )\n" +// " ( 0 8 10 -12 )\n" +// " ( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion addition assignment (unaligned/unpadded)"; +// +// using blaze::unaligned; +// using blaze::unpadded; +// using blaze::rowMajor; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// using UnalignedUnpadded = blaze::CustomMatrix; +// std::unique_ptr memory( new int[21] ); +// UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); +// m(0,0) = 0; +// m(0,1) = 0; +// m(0,2) = 0; +// m(0,3) = 0; +// m(1,0) = 0; +// m(1,1) = 1; +// m(1,2) = 0; +// m(1,3) = 0; +// m(2,0) = -2; +// m(2,1) = 0; +// m(2,2) = -3; +// m(2,3) = 0; +// m(3,0) = 0; +// m(3,1) = 4; +// m(3,2) = 5; +// m(3,3) = -6; +// m(4,0) = 7; +// m(4,1) = -8; +// m(4,2) = 9; +// m(4,3) = 10; +// +// quatslice2 += m; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || +// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || +// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 2 0 0 )\n" +// " ( -4 0 -6 0 )\n" +// " ( 0 8 10 -12 )\n" +// " ( 14 -16 18 20 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice subtraction assignment operators. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the subtraction assignment operators of the QuatSlice +//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testSubAssign() +//{ +// //===================================================================================== +// // QuatSlice subtraction assignment +// //===================================================================================== +// +// { +// test_ = "QuatSlice subtraction assignment"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 -= blaze::quatslice( quat_, 0UL ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 0UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || +// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // dense quaternion subtraction assignment +// //===================================================================================== +// +// { +// test_ = "dense quaternion subtraction assignment (mixed type)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// const blaze::DynamicMatrix vec{{0, 0, 0, 0}, +// {0, 1, 0, 0}, +// {-2, 0, -3, 0}, +// {0, 4, 5, -6}, +// {7, -8, 9, 10}}; +// +// quatslice2 -= vec; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 0UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || +// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// } +// } +// +// { +// test_ = "dense quaternion subtraction assignment (aligned/padded)"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// using AlignedPadded = blaze::CustomMatrix; +// std::unique_ptr memory( blaze::allocate( 80UL ) ); +// AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); +// m(0,0) = 0; +// m(0,1) = 0; +// m(0,2) = 0; +// m(0,3) = 0; +// m(1,0) = 0; +// m(1,1) = 1; +// m(1,2) = 0; +// m(1,3) = 0; +// m(2,0) = -2; +// m(2,1) = 0; +// m(2,2) = -3; +// m(2,3) = 0; +// m(3,0) = 0; +// m(3,1) = 4; +// m(3,2) = 5; +// m(3,3) = -6; +// m(4,0) = 7; +// m(4,1) = -8; +// m(4,2) = 9; +// m(4,3) = 10; +// +// quatslice2 -= m; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 0UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || +// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion subtraction assignment (unaligned/unpadded)"; +// +// using blaze::unaligned; +// using blaze::unpadded; +// using blaze::rowMajor; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// using UnalignedUnpadded = blaze::CustomMatrix; +// std::unique_ptr memory( new int[21] ); +// UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); +// m(0,0) = 0; +// m(0,1) = 0; +// m(0,2) = 0; +// m(0,3) = 0; +// m(1,0) = 0; +// m(1,1) = 1; +// m(1,2) = 0; +// m(1,3) = 0; +// m(2,0) = -2; +// m(2,1) = 0; +// m(2,2) = -3; +// m(2,3) = 0; +// m(3,0) = 0; +// m(3,1) = 4; +// m(3,2) = 5; +// m(3,3) = -6; +// m(4,0) = 7; +// m(4,1) = -8; +// m(4,2) = 9; +// m(4,3) = 10; +// +// quatslice2 -= m; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 0UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || +// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice multiplication assignment operators. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the multiplication assignment operators of the QuatSlice +//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testMultAssign() +//{ +// //===================================================================================== +// // QuatSlice multiplication assignment +// //===================================================================================== +// +// { +// test_ = "QuatSlice multiplication assignment"; +// +// initialize(); +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// quatslice2 *= blaze::quatslice( m, 0UL ); +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || +// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || +// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || +// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || +// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 90 114 138 )\n" +// " ( 54 69 84 )\n" +// " ( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // dense quaternion multiplication assignment +// //===================================================================================== +// +// { +// test_ = "dense quaternion multiplication assignment (mixed type)"; +// +// initialize(); +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// +// const blaze::DynamicMatrix m1{ +// {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; +// +// quatslice2 *= m1; +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || +// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || +// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || +// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || +// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 90 114 138 )\n" +// " ( 54 69 84 )\n" +// " ( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion multiplication assignment (aligned/padded)"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// +// +// using AlignedPadded = blaze::CustomMatrix; +// std::unique_ptr memory( blaze::allocate( 48UL ) ); +// AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); +// m1(0,0) = 1; +// m1(0,1) = 2; +// m1(0,2) = 3; +// m1(1,0) = 4; +// m1(1,1) = 5; +// m1(1,2) = 6; +// m1(2,0) = 7; +// m1(2,1) = 8; +// m1(2,2) = 9; +// +// quatslice2 *= m1; +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || +// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || +// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || +// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || +// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 90 114 138 )\n" +// " ( 54 69 84 )\n" +// " ( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion multiplication assignment (unaligned/unpadded)"; +// +// using blaze::unaligned; +// using blaze::unpadded; +// using blaze::rowMajor; +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// +// using UnalignedUnpadded = blaze::CustomMatrix; +// std::unique_ptr memory( new int[10] ); +// UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); +// m1(0,0) = 1; +// m1(0,1) = 2; +// m1(0,2) = 3; +// m1(1,0) = 4; +// m1(1,1) = 5; +// m1(1,2) = 6; +// m1(2,0) = 7; +// m1(2,1) = 8; +// m1(2,2) = 9; +// +// quatslice2 *= m1; +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || +// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || +// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || +// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || +// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 90 114 138 )\n" +// " ( 54 69 84 )\n" +// " ( 18 24 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice Schur product assignment operators. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the Schur product assignment operators of the QuatSlice +//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testSchurAssign() +//{ +// //===================================================================================== +// // QuatSlice Schur product assignment +// //===================================================================================== +// +// { +// test_ = "QuatSlice Schur product assignment"; +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// quatslice2 %= blaze::quatslice( m, 0UL ); +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || +// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || +// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || +// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || +// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 9 16 21 )\n" +// " ( 24 25 24 )\n" +// " ( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // dense quaternion Schur product assignment +// //===================================================================================== +// +// { +// test_ = "dense vector Schur product assignment (mixed type)"; +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// +// const blaze::DynamicMatrix m1{ +// {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; +// +// quatslice2 %= m1; +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || +// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || +// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || +// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || +// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 9 16 21 )\n" +// " ( 24 25 24 )\n" +// " ( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion Schur product assignment (aligned/padded)"; +// +// using blaze::aligned; +// using blaze::padded; +// using blaze::rowMajor; +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// +// using AlignedPadded = blaze::CustomMatrix; +// std::unique_ptr memory( blaze::allocate( 48UL ) ); +// AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); +// m1(0,0) = 1; +// m1(0,1) = 2; +// m1(0,2) = 3; +// m1(1,0) = 4; +// m1(1,1) = 5; +// m1(1,2) = 6; +// m1(2,0) = 7; +// m1(2,1) = 8; +// m1(2,2) = 9; +// +// quatslice2 %= m1; +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || +// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || +// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || +// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || +// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 9 16 21 )\n" +// " ( 24 25 24 )\n" +// " ( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// { +// test_ = "dense quaternion Schur product assignment (unaligned/unpadded)"; +// +// using blaze::unaligned; +// using blaze::unpadded; +// using blaze::rowMajor; +// +// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, +// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; +// +// RT quatslice2 = blaze::quatslice( m, 1UL ); +// +// using UnalignedUnpadded = blaze::CustomMatrix; +// std::unique_ptr memory( new int[10] ); +// UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); +// m1(0,0) = 1; +// m1(0,1) = 2; +// m1(0,2) = 3; +// m1(1,0) = 4; +// m1(1,1) = 5; +// m1(1,2) = 6; +// m1(2,0) = 7; +// m1(2,1) = 8; +// m1(2,2) = 9; +// +// quatslice2 %= m1; +// +// checkRows ( quatslice2, 3UL ); +// checkColumns ( quatslice2, 3UL ); +// checkCapacity( quatslice2, 9UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( m, 3UL ); +// checkColumns ( m, 3UL ); +// checkQuats ( m, 2UL ); +// checkNonZeros( m, 18UL ); +// +// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || +// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || +// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || +// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || +// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || +// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || +// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || +// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 1 2 3 )\n" +// " ( 4 5 6 )\n" +// " ( 7 8 9 ))\n" +// "(( 9 16 21 )\n" +// " ( 24 25 24 )\n" +// " ( 21 16 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of all QuatSlice (self-)scaling operations. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of all available ways to scale an instance of the QuatSlice +//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testScaling() +//{ +// //===================================================================================== +// // self-scaling (v*=2) +// //===================================================================================== +// +// { +// test_ = "self-scaling (v*=2)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 *= 3; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || +// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || +// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 3 0 0 )\n" +// " ( -6 0 -9 0 )\n" +// " ( 0 12 15 -18 )\n" +// " ( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // self-scaling (v=v*2) +// //===================================================================================== +// +// { +// test_ = "self-scaling (v=v*3)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 = quatslice2 * 3; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || +// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || +// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 3 0 0 )\n" +// " ( -6 0 -9 0 )\n" +// " ( 0 12 15 -18 )\n" +// " ( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // self-scaling (v=3*v) +// //===================================================================================== +// +// { +// test_ = "self-scaling (v=3*v)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 = 3 * quatslice2; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || +// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || +// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 3 0 0 )\n" +// " ( -6 0 -9 0 )\n" +// " ( 0 12 15 -18 )\n" +// " ( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // self-scaling (v/=s) +// //===================================================================================== +// +// { +// test_ = "self-scaling (v/=s)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 /= (1.0/3.0); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || +// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || +// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 3 0 0 )\n" +// " ( -6 0 -9 0 )\n" +// " ( 0 12 15 -18 )\n" +// " ( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // self-scaling (v=v/s) +// //===================================================================================== +// +// { +// test_ = "self-scaling (v=v/s)"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2 = quatslice2 / (1.0/3.0); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || +// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || +// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 3 0 0 )\n" +// " ( -6 0 -9 0 )\n" +// " ( 0 12 15 -18 )\n" +// " ( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// +// //===================================================================================== +// // QuatSlice::scale() +// //===================================================================================== +// +// { +// test_ = "QuatSlice::scale()"; +// +// initialize(); +// +// // Integral scaling the 3rd quatslice +// { +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2.scale( 3 ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || +// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || +// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 3 0 0 )\n" +// " ( -6 0 -9 0 )\n" +// " ( 0 12 15 -18 )\n" +// " ( 21 -24 27 30 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// initialize(); +// +// // Floating point scaling the 3rd quatslice +// { +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// quatslice2.scale( 0.5 ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 19UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -1 || quatslice2(2,1) != 0 || quatslice2(2,2) != -1 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 2 || quatslice2(3,2) != 2 || quatslice2(3,3) != -3 || +// quatslice2(4,0) != 3 || quatslice2(4,1) != -4 || quatslice2(4,2) != 4 || quatslice2(4,3) != 5 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( -1 0 -1 0 )\n( 0 12 2 -3 )\n( 3 -4 4 5 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -1 || quat_(1,2,1) != 0 || quat_(1,2,2) != -1 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 2 || quat_(1,3,2) != 2 || quat_(1,3,3) != -3 || +// quat_(1,4,0) != 3 || quat_(1,4,1) != -4 || quat_(1,4,2) != 4 || quat_(1,4,3) != 5 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed self-scaling operation\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( -1 0 -1 0 )\n" +// " ( 0 2 2 -3 )\n" +// " ( 3 -4 4 5 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice function call operator. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of adding and accessing elements via the function call operator +//// of the QuatSlice specialization. In case an error is detected, a \a std::runtime_error exception +//// is thrown. +//*/ +//void DenseGeneralTest::testFunctionCall() +//{ +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "QuatSlice::operator()"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// // Assignment to the element at index (0,1) +// quatslice2(0,1) = 9; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 11UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 21UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 9 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Assignment to the element at index (2,2) +// quatslice2(2,2) = 0; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 9 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Assignment to the element at index (4,1) +// quatslice2(4,1) = -9; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 9 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Addition assignment to the element at index (0,1) +// quatslice2(0,1) += -3; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Subtraction assignment to the element at index (2,0) +// quatslice2(2,0) -= 6; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -8 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -8 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Multiplication assignment to the element at index (4,0) +// quatslice2(4,0) *= -3; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -8 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != -21 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -8 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Division assignment to the element at index (3,3) +// quatslice2(3,3) /= 2; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -8 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -3 || +// quatslice2(4,0) != -21 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -3 || +// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -8 0 0 0 )\n" +// " ( 0 4 5 -3 )\n" +// " ( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice at() operator. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of adding and accessing elements via the at() operator +//// of the QuatSlice specialization. In case an error is detected, a \a std::runtime_error exception +//// is thrown. +//*/ +//void DenseGeneralTest::testAt() +//{ +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "QuatSlice::at()"; +// +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// // Assignment to the element at index (0,1) +// quatslice2.at(0,1) = 9; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 11UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 21UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 9 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != -3 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || +// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -8 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Assignment to the element at index (2,2) +// quatslice2.at(2,2) = 0; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 9 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || +// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -8 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Assignment to the element at index (4,1) +// quatslice2.at(4,1) = -9; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 9 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || +// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 9 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Addition assignment to the element at index (0,1) +// quatslice2.at(0,1) += -3; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || +// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Subtraction assignment to the element at index (2,0) +// quatslice2.at(2,0) -= 6; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -8 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || +// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -8 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Multiplication assignment to the element at index (4,0) +// quatslice2.at(4,0) *= -3; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -8 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || +// quatslice2.at(4,0) != -21 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -8 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Division assignment to the element at index (3,3) +// quatslice2.at(3,3) /= 2; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || +// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || +// quatslice2.at(2,0) != -8 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || +// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -3 || +// quatslice2.at(4,0) != -21 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -3 || +// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: At() failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 6 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -8 0 0 0 )\n" +// " ( 0 4 5 -3 )\n" +// " ( -21 -9 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the QuatSlice iterator implementation. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the iterator implementation of the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testIterator() +//{ +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// initialize(); +// +// // Testing the Iterator default constructor +// { +// test_ = "Iterator default constructor"; +// +// RT::Iterator it{}; +// +// if( it != RT::Iterator() ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed iterator default constructor\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing the ConstIterator default constructor +// { +// test_ = "ConstIterator default constructor"; +// +// RT::ConstIterator it{}; +// +// if( it != RT::ConstIterator() ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed iterator default constructor\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing conversion from Iterator to ConstIterator +// { +// test_ = "Iterator/ConstIterator conversion"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// RT::ConstIterator it( begin( quatslice2, 2UL ) ); +// +// if( it == end( quatslice2, 2UL ) || *it != -2 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Failed iterator conversion detected\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Counting the number of elements in 1st quatslice via Iterator (end-begin) +// { +// test_ = "Iterator subtraction (end-begin)"; +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// const ptrdiff_t number( end( quatslice1, 2UL ) - begin( quatslice1, 2UL ) ); +// +// if( number != 4L ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid number of elements detected\n" +// << " Details:\n" +// << " Number of elements : " << number << "\n" +// << " Expected number of elements: 4\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Counting the number of elements in 1st quatslice via Iterator (begin-end) +// { +// test_ = "Iterator subtraction (begin-end)"; +// +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// const ptrdiff_t number( begin( quatslice1, 2UL ) - end( quatslice1, 2UL ) ); +// +// if( number != -4L ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid number of elements detected\n" +// << " Details:\n" +// << " Number of elements : " << number << "\n" +// << " Expected number of elements: -4\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Counting the number of elements in 2nd quatslice via ConstIterator (end-begin) +// { +// test_ = "ConstIterator subtraction (end-begin)"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// const ptrdiff_t number( cend( quatslice2, 2UL ) - cbegin( quatslice2, 2UL ) ); +// +// if( number != 4L ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid number of elements detected\n" +// << " Details:\n" +// << " Number of elements : " << number << "\n" +// << " Expected number of elements: 4\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Counting the number of elements in 2nd quatslice via ConstIterator (begin-end) +// { +// test_ = "ConstIterator subtraction (begin-end)"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// const ptrdiff_t number( cbegin( quatslice2, 2UL ) - cend( quatslice2, 2UL ) ); +// +// if( number != -4L ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid number of elements detected\n" +// << " Details:\n" +// << " Number of elements : " << number << "\n" +// << " Expected number of elements: -4\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing read-only access via ConstIterator +// { +// test_ = "read-only access via ConstIterator"; +// +// RT quatslice3 = blaze::quatslice( quat_, 0UL ); +// RT::ConstIterator it ( cbegin( quatslice3, 4UL ) ); +// RT::ConstIterator end( cend( quatslice3, 4UL ) ); +// +// if( it == end || *it != 7 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid initial iterator detected\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// ++it; +// +// if( it == end || *it != -8 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator pre-increment failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// --it; +// +// if( it == end || *it != 7 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator pre-decrement failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it++; +// +// if( it == end || *it != -8 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator post-increment failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it--; +// +// if( it == end || *it != 7 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator post-decrement failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it += 2UL; +// +// if( it == end || *it != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator addition assignment failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it -= 2UL; +// +// if( it == end || *it != 7 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator subtraction assignment failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it = it + 3UL; +// +// if( it == end || *it != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator/scalar addition failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it = it - 3UL; +// +// if( it == end || *it != 7 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator/scalar subtraction failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// it = 4UL + it; +// +// if( it != end ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Scalar/iterator addition failed\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing assignment via Iterator +// { +// test_ = "assignment via Iterator"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// int value = 6; +// +// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { +// *it = value++; +// } +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 6 || quatslice2(4,1) != 7 || quatslice2(4,2) != 8 || quatslice2(4,3) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 6 || quat_(1,4,1) != 7 || quat_(1,4,2) != 8 || quat_(1,4,3) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 6 7 8 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing addition assignment via Iterator +// { +// test_ = "addition assignment via Iterator"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// int value = 2; +// +// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { +// *it += value++; +// } +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 8 || quatslice2(4,1) != 10 || quatslice2(4,2) != 12 || quatslice2(4,3) != 14 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 8 10 12 14 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 8 || quat_(1,4,1) != 10 || quat_(1,4,2) != 12 || quat_(1,4,3) != 14 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Addition assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 8 10 12 14 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing subtraction assignment via Iterator +// { +// test_ = "subtraction assignment via Iterator"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// int value = 2; +// +// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { +// *it -= value++; +// } +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 6 || quatslice2(4,1) != 7 || quatslice2(4,2) != 8 || quatslice2(4,3) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 6 || quat_(1,4,1) != 7 || quat_(1,4,2) != 8 || quat_(1,4,3) != 9 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subtraction assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 6 7 8 9 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing multiplication assignment via Iterator +// { +// test_ = "multiplication assignment via Iterator"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// int value = 1; +// +// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { +// *it *= value++; +// } +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 6 || quatslice2(4,1) != 14 || quatslice2(4,2) != 24 || quatslice2(4,3) != 36 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 14 24 36 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 6 || quat_(1,4,1) != 14 || quat_(1,4,2) != 24 || quat_(1,4,3) != 36 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Multiplication assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 6 14 24 36 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Testing division assignment via Iterator +// { +// test_ = "division assignment via Iterator"; +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { +// *it /= 2; +// } +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 3 || quatslice2(4,1) != 7 || quatslice2(4,2) != 12 || quatslice2(4,3) != 18 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Division assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 3 7 12 18 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || +// quat_(1,4,0) != 3 || quat_(1,4,1) != 7 || quat_(1,4,2) != 12 || quat_(1,4,3) != 18 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Division assignment via iterator failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 0 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 3 7 12 18 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c nonZeros() member function of the QuatSlice specialization. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c nonZeros() member function of the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testNonZeros() +//{ +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "QuatSlice::nonZeros()"; +// +// initialize(); +// +// // Initialization check +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Initialization failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Changing the number of non-zeros via the dense quatslice +// quatslice2(2, 2) = 0; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 19UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// // Changing the number of non-zeros via the dense quaternion +// quat_(1,3,0) = 5; +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 10UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 20UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 5 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Matrix function call operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 5 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c reset() member function of the QuatSlice specialization. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c reset() member function of the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testReset() +//{ +// using blaze::reset; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "QuatSlice::reset()"; +// +// // Resetting a single element in quatslice 3 +// { +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// reset( quatslice2(2, 2) ); +// +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 19UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Reset operator failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Resetting the 1st quatslice (lvalue) +// { +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// reset( quatslice2 ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 0UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || +// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Reset operation of 1st quatslice failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Resetting the 1st quatslice (rvalue) +// { +// initialize(); +// +// reset( blaze::quatslice( quat_, 1UL ) ); +// +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Reset operation of 1st quatslice failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c clear() function with the QuatSlice specialization. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c clear() function with the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testClear() +//{ +// using blaze::clear; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "clear() function"; +// +// // Clearing a single element in quatslice 1 +// { +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// clear( quatslice2(2, 2) ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 9UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 19UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || +// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Clear operation failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Clearing the 3rd quatslice (lvalue) +// { +// initialize(); +// +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// clear( quatslice2 ); +// +// checkRows ( quatslice2, 5UL ); +// checkColumns ( quatslice2, 4UL ); +// checkCapacity( quatslice2, 20UL ); +// checkNonZeros( quatslice2, 0UL ); +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || +// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || +// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || +// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || +// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Clear operation of 3rd quatslice failed\n" +// << " Details:\n" +// << " Result:\n" << quatslice2 << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // Clearing the 4th quatslice (rvalue) +// { +// initialize(); +// +// clear( blaze::quatslice( quat_, 1UL ) ); +// +// checkRows ( quat_, 5UL ); +// checkColumns ( quat_, 4UL ); +// checkQuats ( quat_, 2UL ); +// checkNonZeros( quat_, 10UL ); +// +// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || +// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || +// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || +// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || +// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || +// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || +// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || +// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || +// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || +// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Clear operation of 1st quatslice failed\n" +// << " Details:\n" +// << " Result:\n" << quat_ << "\n" +// << " Expected result:\n(( 0 0 0 0 )\n" +// " ( 0 1 0 0 )\n" +// " ( -2 0 -3 0 )\n" +// " ( 0 4 5 -6 )\n" +// " ( 7 -8 9 10 ))\n" +// "(( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 )\n" +// " ( 0 0 0 0 ))\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c isDefault() function with the QuatSlice specialization. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c isDefault() function with the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testIsDefault() +//{ +// using blaze::isDefault; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "isDefault() function"; +// +// initialize(); +// +// // isDefault with default quatslice +// { +// RT quatslice0 = blaze::quatslice( quat_, 0UL ); +// quatslice0 = 0; +// +// if( isDefault( quatslice0(0, 0) ) != true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isDefault evaluation\n" +// << " Details:\n" +// << " QuatSlice element: " << quatslice0(0, 0) << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( isDefault( quatslice0 ) != true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isDefault evaluation\n" +// << " Details:\n" +// << " QuatSlice:\n" << quatslice0 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isDefault with non-default quatslice +// { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// +// if( isDefault( quatslice1(1, 1) ) != false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isDefault evaluation\n" +// << " Details:\n" +// << " QuatSlice element: " << quatslice1(1, 1) << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( isDefault( quatslice1 ) != false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isDefault evaluation\n" +// << " Details:\n" +// << " QuatSlice:\n" << quatslice1 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c isSame() function with the QuatSlice specialization. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c isSame() function with the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testIsSame() +//{ +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "isSame() function"; +// +// // isSame with quatching quatslices +// { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices +// { +// RT quatslice1 = blaze::quatslice( quat_, 0UL ); +// RT quatslice2 = blaze::quatslice( quat_, 1UL ); +// +// quatslice1 = 42; +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatslice and quatching subquaternion +// { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto sv = blaze::subquaternion( quatslice1, 0UL, 0UL, 5UL, 4UL ); +// +// if( blaze::isSame( quatslice1, sv ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " Dense quatslice:\n" << quatslice1 << "\n" +// << " Dense subquaternion:\n" << sv << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( sv, quatslice1 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " Dense quatslice:\n" << quatslice1 << "\n" +// << " Dense subquaternion:\n" << sv << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatslice and non-quatching subquaternion (different size) +// { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto sv = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 3UL ); +// +// if( blaze::isSame( quatslice1, sv ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " Dense quatslice:\n" << quatslice1 << "\n" +// << " Dense subquaternion:\n" << sv << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( sv, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " Dense quatslice:\n" << quatslice1 << "\n" +// << " Dense subquaternion:\n" << sv << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatslice and non-quatching subquaternion (different offset) +// { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto sv = blaze::subquaternion( quatslice1, 1UL, 1UL, 3UL, 3UL ); +// +// if( blaze::isSame( quatslice1, sv ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " Dense quatslice:\n" << quatslice1 << "\n" +// << " Dense subquaternion:\n" << sv << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( sv, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " Dense quatslice:\n" << quatslice1 << "\n" +// << " Dense subquaternion:\n" << sv << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatching quatslices on a common subquaternion +// { +// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto quatslice2 = blaze::quatslice( sm, 1UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices on a common subquaternion +// { +// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); +// auto quatslice1 = blaze::quatslice( sm, 0UL ); +// auto quatslice2 = blaze::quatslice( sm, 1UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatching subquaternion on quaternion and subquaternion +// { +// auto sm = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto quatslice2 = blaze::quatslice( sm , 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices on quaternion and subquaternion (different quatslice) +// { +// auto sm = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( quat_, 0UL ); +// auto quatslice2 = blaze::quatslice( sm , 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices on quaternion and subquaternion (different size) +// { +// auto sm = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 4UL, 3UL ); +// auto quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto quatslice2 = blaze::quatslice( sm , 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatching quatslices on two subquaternions +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices on two subquaternions (different quatslice) +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 0UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices on two subquaternions (different size) +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 4UL, 3UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslices on two subquaternions (different offset) +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 4UL, 2UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// +// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( blaze::isSame( quatslice2, quatslice1 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First quatslice:\n" << quatslice1 << "\n" +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatching quatslice subquatrices on a subquaternion +// { +// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// auto sv2 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// +// if( blaze::isSame( sv1, sv2 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First subquaternion:\n" << sv1 << "\n" +// << " Second subquaternion:\n" << sv2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslice subquaternions on a subquaternion (different size) +// { +// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// auto sv2 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 2UL ); +// +// if( blaze::isSame( sv1, sv2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First subquaternion:\n" << sv1 << "\n" +// << " Second subquaternion:\n" << sv2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslice subquaternions on a subquaternion (different offset) +// { +// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// auto sv2 = blaze::subquaternion( quatslice1, 0UL, 1UL, 2UL, 1UL ); +// +// if( blaze::isSame( sv1, sv2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First subquaternion:\n" << sv1 << "\n" +// << " Second subquaternion:\n" << sv2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with quatching quatslice subquaternions on two subquaternions +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 2UL ); +// auto sv2 = blaze::subquaternion( quatslice2, 0UL, 0UL, 3UL, 2UL ); +// +// if( blaze::isSame( sv1, sv2 ) == false ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First subquaternion:\n" << sv1 << "\n" +// << " Second subquaternion:\n" << sv2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslice subquaternions on two subquaternions (different size) +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 2UL ); +// auto sv2 = blaze::subquaternion( quatslice2, 0UL, 0UL, 2UL, 2UL ); +// +// if( blaze::isSame( sv1, sv2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First subquaternion:\n" << sv1 << "\n" +// << " Second subquaternion:\n" << sv2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// // isSame with non-quatching quatslice subquaternions on two subquaternions (different offset) +// { +// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 2UL ); +// auto sv2 = blaze::subquaternion( quatslice2, 0UL, 1UL, 3UL, 2UL ); +// +// if( blaze::isSame( sv1, sv2 ) == true ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Invalid isSame evaluation\n" +// << " Details:\n" +// << " First subquaternion:\n" << sv1 << "\n" +// << " Second subquaternion:\n" << sv2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c subquaternion() function with the QuatSlice specialization. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c subquaternion() function used with the QuatSlice specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testSubquaternion() +//{ +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "subquaternion() function"; +// +// initialize(); +// +// { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto sm = blaze::subquaternion( quatslice1, 1UL, 1UL, 2UL, 3UL ); +// +// if( sm(0,0) != 1 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subscript operator access failed\n" +// << " Details:\n" +// << " Result: " << sm(0,0) << "\n" +// << " Expected result: 1\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( *sm.begin(1) != 0 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator access failed\n" +// << " Details:\n" +// << " Result: " << *sm.begin(1) << "\n" +// << " Expected result: 0\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// try { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto sm = blaze::subquaternion( quatslice1, 4UL, 0UL, 4UL, 4UL ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds subquaternion succeeded\n" +// << " Details:\n" +// << " Result:\n" << sm << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// +// try { +// RT quatslice1 = blaze::quatslice( quat_, 1UL ); +// auto sm = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 6UL ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds subquaternion succeeded\n" +// << " Details:\n" +// << " Result:\n" << sm << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +//} +////************************************************************************************************* +// +////************************************************************************************************* +///*!\brief Test of the \c row() function with the Subquaternion class template. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c row() function with the Subquaternion specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testRow() +//{ +// using blaze::quatslice; +// using blaze::row; +// using blaze::aligned; +// using blaze::unaligned; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "Quatslice row() function"; +// +// initialize(); +// +// { +// RT quatslice1 = quatslice( quat_, 0UL ); +// RT quatslice2 = quatslice( quat_, 1UL ); +// auto row1 = row( quatslice1, 1UL ); +// auto row2 = row( quatslice2, 1UL ); +// +// if( row1 != row2 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Row function failed\n" +// << " Details:\n" +// << " Result:\n" << row1 << "\n" +// << " Expected result:\n" << row2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( row1[1] != row2[1] ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subscript operator access failed\n" +// << " Details:\n" +// << " Result: " << row1[1] << "\n" +// << " Expected result: " << row2[1] << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( *row1.begin() != *row2.begin() ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator access failed\n" +// << " Details:\n" +// << " Result: " << *row1.begin() << "\n" +// << " Expected result: " << *row2.begin() << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// try { +// RT quatslice1 = quatslice( quat_, 0UL ); +// auto row8 = row( quatslice1, 8UL ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds row succeeded\n" +// << " Details:\n" +// << " Result:\n" << row8 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c rows() function with the Subquaternion class template. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c rows() function with the Subquaternion specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testRows() +//{ +// using blaze::quatslice; +// using blaze::rows; +// using blaze::aligned; +// using blaze::unaligned; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "Quatslice rows() function"; +// +// initialize(); +// +// { +// RT quatslice1 = quatslice( quat_, 0UL ); +// RT quatslice2 = quatslice( quat_, 1UL ); +// auto rs1 = rows( quatslice1, { 0UL, 2UL, 4UL, 3UL } ); +// auto rs2 = rows( quatslice2, { 0UL, 2UL, 4UL, 3UL } ); +// +// if( rs1 != rs2 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Rows function failed\n" +// << " Details:\n" +// << " Result:\n" << rs1 << "\n" +// << " Expected result:\n" << rs2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( rs1(1,1) != rs2(1,1) ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator access failed\n" +// << " Details:\n" +// << " Result: " << rs1(1,1) << "\n" +// << " Expected result: " << rs2(1,1) << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( *rs1.begin( 1UL ) != *rs2.begin( 1UL ) ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator access failed\n" +// << " Details:\n" +// << " Result: " << *rs1.begin( 1UL ) << "\n" +// << " Expected result: " << *rs2.begin( 1UL ) << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// try { +// RT quatslice1 = quatslice( quat_, 1UL ); +// auto rs = rows( quatslice1, { 8UL } ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds row selection succeeded\n" +// << " Details:\n" +// << " Result:\n" << rs << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c column() function with the Subquaternion class template. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c column() function with the Subquaternion specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testColumn() +//{ +// using blaze::quatslice; +// using blaze::column; +// using blaze::aligned; +// using blaze::unaligned; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "Quatslice column() function"; +// +// initialize(); +// +// { +// RT quatslice1 = quatslice( quat_, 0UL ); +// RT quatslice2 = quatslice( quat_, 1UL ); +// auto col1 = column( quatslice1, 1UL ); +// auto col2 = column( quatslice2, 1UL ); +// +// if( col1 != col2 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Column function failed\n" +// << " Details:\n" +// << " Result:\n" << col1 << "\n" +// << " Expected result:\n" << col2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( col1[1] != col2[1] ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subscript operator access failed\n" +// << " Details:\n" +// << " Result: " << col1[1] << "\n" +// << " Expected result: " << col2[1] << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( *col1.begin() != *col2.begin() ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator access failed\n" +// << " Details:\n" +// << " Result: " << *col1.begin() << "\n" +// << " Expected result: " << *col2.begin() << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// try { +// RT quatslice1 = quatslice( quat_, 0UL ); +// auto col16 = column( quatslice1, 16UL ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds column succeeded\n" +// << " Details:\n" +// << " Result:\n" << col16 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c columns() function with the Subquaternion class template. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c columns() function with the Subquaternion specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testColumns() +//{ +// using blaze::quatslice; +// using blaze::rows; +// using blaze::aligned; +// using blaze::unaligned; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "columns() function"; +// +// initialize(); +// +// { +// RT quatslice1 = quatslice( quat_, 0UL ); +// RT quatslice2 = quatslice( quat_, 1UL ); +// auto cs1 = columns( quatslice1, { 0UL, 2UL, 2UL, 3UL } ); +// auto cs2 = columns( quatslice2, { 0UL, 2UL, 2UL, 3UL } ); +// +// if( cs1 != cs2 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Rows function failed\n" +// << " Details:\n" +// << " Result:\n" << cs1 << "\n" +// << " Expected result:\n" << cs2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( cs1(1,1) != cs2(1,1) ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Function call operator access failed\n" +// << " Details:\n" +// << " Result: " << cs1(1,1) << "\n" +// << " Expected result: " << cs2(1,1) << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( *cs1.begin( 1UL ) != *cs2.begin( 1UL ) ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator access failed\n" +// << " Details:\n" +// << " Result: " << *cs1.begin( 1UL ) << "\n" +// << " Expected result: " << *cs2.begin( 1UL ) << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// try { +// RT quatslice1 = quatslice( quat_, 1UL ); +// auto cs = columns( quatslice1, { 16UL } ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds column selection succeeded\n" +// << " Details:\n" +// << " Result:\n" << cs << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +//} +////************************************************************************************************* +// +// +////************************************************************************************************* +///*!\brief Test of the \c band() function with the Subquaternion class template. +//// +//// \return void +//// \exception std::runtime_error Error detected. +//// +//// This function performs a test of the \c band() function with the Subquaternion specialization. +//// In case an error is detected, a \a std::runtime_error exception is thrown. +//*/ +//void DenseGeneralTest::testBand() +//{ +// using blaze::quatslice; +// using blaze::band; +// using blaze::aligned; +// using blaze::unaligned; +// +// +// //===================================================================================== +// // quaternion tests +// //===================================================================================== +// +// { +// test_ = "Quatslice band() function"; +// +// initialize(); +// +// { +// RT quatslice1 = quatslice( quat_, 0UL ); +// RT quatslice2 = quatslice( quat_, 1UL ); +// auto b1 = band( quatslice1, 1L ); +// auto b2 = band( quatslice2, 1L ); +// +// if( b1 != b2 ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Band function failed\n" +// << " Details:\n" +// << " Result:\n" << b1 << "\n" +// << " Expected result:\n" << b2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( b1[1] != b2[1] ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Subscript operator access failed\n" +// << " Details:\n" +// << " Result: " << b1[1] << "\n" +// << " Expected result: " << b2[1] << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// +// if( *b1.begin() != *b2.begin() ) { +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Iterator access failed\n" +// << " Details:\n" +// << " Result: " << *b1.begin() << "\n" +// << " Expected result: " << *b2.begin() << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } +// +// try { +// RT quatslice1 = quatslice( quat_, 1UL ); +// auto b8 = band( quatslice1, -8L ); +// +// std::ostringstream oss; +// oss << " Test: " << test_ << "\n" +// << " Error: Setup of out-of-bounds band succeeded\n" +// << " Details:\n" +// << " Result:\n" << b8 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// catch( std::invalid_argument& ) {} +// } +//} +////************************************************************************************************* + + + +//================================================================================================= +// +// UTILITY FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Initialization of all member quatrices. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function initializes all member quatrices to specific predetermined values. +*/ +void DenseGeneralTest::initialize() +{ + // Initializing the quatslice-major dynamic quaternion + //quat_.reset(); + //quat_(0,1,1) = 1; + //quat_(0,2,0) = -2; + //quat_(0,2,2) = -3; + //quat_(0,3,1) = 4; + //quat_(0,3,2) = 5; + //quat_(0,3,3) = -6; + //quat_(0,4,0) = 7; + //quat_(0,4,1) = -8; + //quat_(0,4,2) = 9; + //quat_(0,4,3) = 10; + //quat_(1,1,1) = 1; + //quat_(1,2,0) = -2; + //quat_(1,2,2) = -3; + //quat_(1,3,1) = 4; + //quat_(1,3,2) = 5; + //quat_(1,3,3) = -6; + //quat_(1,4,0) = 7; + //quat_(1,4,1) = -8; + //quat_(1,4,2) = 9; + //quat_(1,4,3) = 10; +} +//************************************************************************************************* + +} // namespace quatslice + +} // namespace mathtest + +} // namespace blazetest + + + + +//================================================================================================= +// +// MAIN FUNCTION +// +//================================================================================================= + +#if defined(BLAZE_USE_HPX_THREADS) +#include +#endif + +//************************************************************************************************* +int main() +{ + std::cout << " Running QuatSlice dense general test..." << std::endl; + + try + { + RUN_QUATSLICE_DENSEGENERAL_TEST; + } + catch( std::exception& ex ) { + std::cerr << "\n\n ERROR DETECTED during QuatSlice dense general test:\n" + << ex.what() << "\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} +//************************************************************************************************* From 23af66c75e9dde26fa66a7ae519cbff27ca7882a Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Mon, 1 Jul 2019 14:05:31 -0500 Subject: [PATCH 09/14] working towards running the include test --- blaze_tensor/math/DenseArray.h | 2 +- blaze_tensor/math/dense/CustomArray.h | 82 + blaze_tensor/math/dense/DenseTensor.h | 20 +- blaze_tensor/math/dense/DynamicArray.h | 86 +- blaze_tensor/math/dense/DynamicTensor.h | 30 +- blaze_tensor/math/expressions/Array.h | 18 + blaze_tensor/math/views/quatslice/Dense.h | 94 +- .../mathtest/quatslice/DenseGeneralTest.h | 5 +- .../src/mathtest/quatslice/CMakeLists.txt | 1 + .../mathtest/quatslice/DenseGeneralTest.cpp | 6315 ++++++++--------- 10 files changed, 3148 insertions(+), 3505 deletions(-) diff --git a/blaze_tensor/math/DenseArray.h b/blaze_tensor/math/DenseArray.h index 8da5247..4a66beb 100644 --- a/blaze_tensor/math/DenseArray.h +++ b/blaze_tensor/math/DenseArray.h @@ -127,7 +127,7 @@ // #include #include #include -#include +//#include #include #include // #include diff --git a/blaze_tensor/math/dense/CustomArray.h b/blaze_tensor/math/dense/CustomArray.h index ee6ddd5..ba96635 100644 --- a/blaze_tensor/math/dense/CustomArray.h +++ b/blaze_tensor/math/dense/CustomArray.h @@ -517,6 +517,10 @@ class CustomArray //@{ inline static constexpr size_t num_dimensions() noexcept { return N; } inline constexpr std::array< size_t, N > const& dimensions() const noexcept; + inline size_t quats() const noexcept; + inline size_t pages() const noexcept; + inline size_t rows() const noexcept; + inline size_t columns() const noexcept; template < size_t Dim > inline size_t dimension() const noexcept; inline size_t spacing() const noexcept; @@ -1006,6 +1010,84 @@ inline constexpr std::array< size_t, N > const& CustomArray::di //************************************************************************************************* +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::quats() const noexcept +{ + return dims_[3]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::pages() const noexcept +{ + return dims_[2]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::rows() const noexcept +{ + return dims_[1]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type // Data type of the array + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +inline size_t CustomArray::columns() const noexcept +{ + return dims_[0]; +} +//************************************************************************************************* //================================================================================================= diff --git a/blaze_tensor/math/dense/DenseTensor.h b/blaze_tensor/math/dense/DenseTensor.h index db0978b..af5eb37 100644 --- a/blaze_tensor/math/dense/DenseTensor.h +++ b/blaze_tensor/math/dense/DenseTensor.h @@ -235,11 +235,11 @@ template< typename TT // Type of the left-hand side dense tensor inline auto operator*=( DenseTensor& tens, ST scalar ) -> EnableIf_t< IsNumeric_v, TT& > { - if( IsRestricted_v ) { - if( !tryMult( ~tens, 0UL, 0UL, 0UL, (~tens).pages(), (~tens).rows(), (~tens).columns(), scalar ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted tensor" ); - } - } + //if( IsRestricted_v ) { + // if( !tryMult( ~tens, 0UL, 0UL, 0UL, (~tens).pages(), (~tens).rows(), (~tens).columns(), scalar ) ) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted tensor" ); + // } + //} BLAZE_DECLTYPE_AUTO( left, derestrict( ~tens ) ); @@ -299,11 +299,11 @@ inline auto operator/=( DenseTensor& tens, ST scalar ) BLAZE_USER_ASSERT( !isZero( scalar ), "Division by zero detected" ); - if( IsRestricted_v ) { - if( !tryDiv( ~tens, 0UL, 0UL, 0UL, (~tens).pages(), (~tens).rows(), (~tens).columns(), scalar ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted tensor" ); - } - } + //if( IsRestricted_v ) { + // if( !tryDiv( ~tens, 0UL, 0UL, 0UL, (~tens).pages(), (~tens).rows(), (~tens).columns(), scalar ) ) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid scaling of restricted tensor" ); + // } + //} BLAZE_DECLTYPE_AUTO( left, derestrict( ~tens ) ); diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index 2ddeb01..ccfb257 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -64,9 +64,11 @@ #include #include #include +#include #include #include -#include +//#include +#include #include #include #include @@ -311,6 +313,10 @@ class DynamicArray //@{ inline static constexpr size_t num_dimensions() noexcept { return N; } inline constexpr std::array< size_t, N > const& dimensions() const noexcept; + inline size_t quats() const noexcept; + inline size_t pages() const noexcept; + inline size_t rows() const noexcept; + inline size_t columns() const noexcept; template < size_t Dim > inline size_t dimension() const noexcept; inline size_t spacing() const noexcept; @@ -2552,6 +2558,73 @@ inline constexpr std::array< size_t, N > const& DynamicArray< N, Type >::dimensi //************************************************************************************************* +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray< N, Type >::quats() const noexcept +{ + return dims_[3]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray< N, Type >::pages() const noexcept +{ + return dims_[2]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray< N, Type >::rows() const noexcept +{ + return dims_[1]; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Calculate index of first element in given row. +// +// \param value The index-array for the row access. +// \return The index of the first element in the given row. +// +// This function calculates the overall index of the first of the give row +*/ +template< size_t N // The dimensionality of the array + , typename Type > // Data type of the array +inline size_t DynamicArray< N, Type >::columns() const noexcept +{ + return dims_[0]; +} +//************************************************************************************************* + //================================================================================================= // @@ -3986,17 +4059,16 @@ struct DivTraitEval2< DynamicArray, T2 //************************************************************************************************* /*! \cond BLAZE_INTERNAL */ -template< size_t M, size_t N, typename ET, size_t I > -struct ArraySliceTraitEval2< M, DynamicArray, I > -{ - using Type = DynamicArray< N - 1, ET >; -}; +//template< size_t M, size_t N, typename ET, size_t I > +//struct ArraySliceTraitEval2< M, DynamicArray, I > +//{ +// using Type = DynamicArray< N - 1, ET >; +//}; /*! \endcond */ //************************************************************************************************* - //================================================================================================= // // MAPTRAIT SPECIALIZATIONS diff --git a/blaze_tensor/math/dense/DynamicTensor.h b/blaze_tensor/math/dense/DynamicTensor.h index 4fc37f7..d575f1c 100644 --- a/blaze_tensor/math/dense/DynamicTensor.h +++ b/blaze_tensor/math/dense/DynamicTensor.h @@ -3511,18 +3511,24 @@ struct PageSliceTraitEval2< //************************************************************************************************* /*! \cond BLAZE_INTERNAL */ -template -struct QuatSliceTraitEval2< - MT, M, - EnableIf_t< IsDenseArray_v && - ( Size_v< MT,1UL > == DefaultSize_v || - Size_v< MT,2UL > == DefaultSize_v || - Size_v< MT,3UL > == DefaultSize_v ) && - ( MaxSize_v< MT,1UL > == DefaultMaxSize_v || - MaxSize_v< MT,2UL > == DefaultMaxSize_v || - MaxSize_v< MT,3UL > == DefaultMaxSize_v ) > > -{ - using Type = DynamicTensor< RemoveConst_t< ElementType_t > >; +//template +//struct QuatSliceTraitEval2< +// MT, M, +// EnableIf_t< IsDenseArray_v && +// ( Size_v< MT,1UL > == DefaultSize_v || +// Size_v< MT,2UL > == DefaultSize_v || +// Size_v< MT,3UL > == DefaultSize_v ) && +// ( MaxSize_v< MT,1UL > == DefaultMaxSize_v || +// MaxSize_v< MT,2UL > == DefaultMaxSize_v || +// MaxSize_v< MT,3UL > == DefaultMaxSize_v ) > > +//{ +// using Type = DynamicTensor< RemoveConst_t< ElementType_t > >; +//}; + +template< typename ET, size_t I > +struct QuatSliceTraitEval2< DynamicArray<4, ET>, I > +{ + using Type = DynamicTensor< ET >; }; /*! \endcond */ //************************************************************************************************* diff --git a/blaze_tensor/math/expressions/Array.h b/blaze_tensor/math/expressions/Array.h index 0d4ef17..e6874e3 100644 --- a/blaze_tensor/math/expressions/Array.h +++ b/blaze_tensor/math/expressions/Array.h @@ -702,6 +702,9 @@ BLAZE_ALWAYS_INLINE constexpr size_t columns( const Array& array ) noexcept; template< typename MT > BLAZE_ALWAYS_INLINE constexpr size_t pages( const Array& array ) noexcept; +template< typename MT > +BLAZE_ALWAYS_INLINE constexpr size_t quats( const Array& array ) noexcept; + template< typename MT > BLAZE_ALWAYS_INLINE constexpr size_t size( const Array& array ) noexcept; @@ -928,6 +931,21 @@ BLAZE_ALWAYS_INLINE constexpr size_t pages( const Array& array ) noexcept //************************************************************************************************* +//************************************************************************************************* +/*!\brief Returns the current number of quats of the array. +// \ingroup array +// +// \param array The given array. +// \return The number of quats of the array. +*/ +template< typename MT > // Type of the array +BLAZE_ALWAYS_INLINE constexpr size_t quats( const Array& array ) noexcept +{ + return (~array).quats(); +} +//************************************************************************************************* + + //************************************************************************************************* /*!\brief Returns the total number of elements of the array. // \ingroup array diff --git a/blaze_tensor/math/views/quatslice/Dense.h b/blaze_tensor/math/views/quatslice/Dense.h index 3a1e106..e087c82 100644 --- a/blaze_tensor/math/views/quatslice/Dense.h +++ b/blaze_tensor/math/views/quatslice/Dense.h @@ -94,6 +94,7 @@ #include #include +#include #include #include #include @@ -132,11 +133,11 @@ class QuatSlice //! Type of this QuatSlice instance. using This = QuatSlice; - using BaseType = DenseTensor; //!< Base type of this QuatSlice instance. + using BaseType = DenseTensor; //!< Base type of this QuatSlice instance. using ViewedType = AT; //!< The type viewed by this QuatSlice instance. using ResultType = QuatSliceTrait_t; //!< Result type for expression template evaluations. //using OppositeType = OppositeType_t; //!< Result type with opposite storage order for expression template evaluations. - using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + //using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. using ElementType = ElementType_t; //!< Type of the quatslice elements. using SIMDType = SIMDTrait_t; //!< SIMD type of the quatslice elements. using ReturnType = ReturnType_t; //!< Return type for expression template evaluations @@ -548,7 +549,7 @@ template< typename AT // Type of the dense quaternion inline typename QuatSlice::Pointer QuatSlice::data() noexcept { - return quaternion_.data( quat(), 0, 0 ); + return quaternion_.data( 0, 0, quat() ); } /*! \endcond */ //************************************************************************************************* @@ -568,7 +569,7 @@ template< typename AT // Type of the dense quaternion inline typename QuatSlice::ConstPointer QuatSlice::data() const noexcept { - return quaternion_.data( quat(), 0, 0 ); + return quaternion_.data( 0, 0, quat() ); } /*! \endcond */ //************************************************************************************************* @@ -588,7 +589,7 @@ template< typename AT // Type of the dense quaternion inline typename QuatSlice::Pointer QuatSlice::data( size_t i, size_t k ) noexcept { - return quaternion_.data( quat(), k, i ); + return quaternion_.data( k, i, quat() ); } /*! \endcond */ //************************************************************************************************* @@ -606,9 +607,9 @@ inline typename QuatSlice::Pointer template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstPointer - QuatSlice::data( size_t i, size_t k ) const noexcept + QuatSlice::data( size_t k, size_t i ) const noexcept { - return quaternion_.data( quat(), k, i ); + return quaternion_.data( k, i, quat() ); } /*! \endcond */ //************************************************************************************************* @@ -626,9 +627,9 @@ inline typename QuatSlice::ConstPointer template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::Iterator - QuatSlice::begin( size_t i, size_t k ) + QuatSlice::begin( size_t k, size_t i ) { - return quaternion_.begin( quat(), k, i ); + return quaternion_.begin( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -646,9 +647,9 @@ inline typename QuatSlice::Iterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::begin( size_t i, size_t k ) const + QuatSlice::begin( size_t k, size_t i ) const { - return quaternion_.cbegin( quat(), k, i ); + return quaternion_.cbegin( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -666,9 +667,9 @@ inline typename QuatSlice::ConstIterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::cbegin( size_t i, size_t k ) const + QuatSlice::cbegin( size_t k, size_t i ) const { - return quaternion_.cbegin( quat(), k, i ); + return quaternion_.cbegin( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -686,9 +687,9 @@ inline typename QuatSlice::ConstIterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::Iterator - QuatSlice::end( size_t i, size_t k ) + QuatSlice::end( size_t k, size_t i ) { - return quaternion_.end( quat(), k, i ); + return quaternion_.end( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -706,9 +707,9 @@ inline typename QuatSlice::Iterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::end( size_t i, size_t k ) const + QuatSlice::end( size_t k, size_t i ) const { - return quaternion_.cend( quat(), k, i ); + return quaternion_.cend( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -726,9 +727,9 @@ inline typename QuatSlice::ConstIterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::cend( size_t i, size_t k ) const + QuatSlice::cend( size_t k, size_t i ) const { - return quaternion_.cend( quat(), k, i ); + return quaternion_.cend( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -762,12 +763,10 @@ inline QuatSlice& for( size_t k=0; k || IsTriangular_v || trySet( quaternion_, i, j, k, rhs ) ) + for (size_t j = 0; j < columns(); ++j) { + if (!IsRestricted_v || IsTriangular_v || trySet(quaternion_, std::array{ i, j, k }, rhs)) left(quat(),k,i,j) = rhs; } } @@ -798,16 +797,17 @@ template< typename AT // Type of the dense quaternion inline QuatSlice& QuatSlice::operator=( initializer_list< initializer_list< initializer_list > > list ) { - if (list.size() > pages() ) { + if (list.size() != pages() ) { BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to quatslice" ); } - if( IsRestricted_v ) { - const InitializerTensor tmp( list, rows(), columns() ); - if( !tryAssign( quaternion_, tmp, quat(), 0UL, 0UL, 0UL ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); - } - } + //if( IsRestricted_v ) { + // const InitializerTensor tmp( list, rows(), columns() ); + // if (!tryAssign(quaternion_, tmp, std::array{quat(),0,0,0})) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + // } + //} + decltype(auto) left( derestrict( *this ) ); @@ -815,7 +815,7 @@ inline QuatSlice& for( const auto& colList : list ) { size_t i( 0UL ); for( const auto& rowList : colList ) { - std::fill( std::copy( rowList.begin(), rowList.end(), left.begin(i, k) ), left.end(i, k), ElementType() ); + std::fill( std::copy( rowList.begin(), rowList.end(), left.begin( k,i) ), left.end(k,i), ElementType() ); ++i; } ++k; @@ -854,9 +854,9 @@ inline QuatSlice& BLAZE_THROW_INVALID_ARGUMENT( "QuatSlice sizes do not match" ); } - if( !tryAssign( quaternion_, rhs, quat(), 0UL, 0UL, 0UL ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); - } + //if (!tryAssign(quaternion_, rhs, std::array{quat(), 0UL, 0UL, 0UL})) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + //} decltype(auto) left( derestrict( *this ) ); @@ -906,9 +906,9 @@ inline QuatSlice& using Right = If_t< IsRestricted_v, CompositeType_t, const AT2& >; Right right( ~rhs ); - if( !tryAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); - } + //if( !tryAssign( quaternion_, right, std::array{quat(), 0UL, 0UL, 0UL} ) ) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + //} decltype(auto) left( derestrict( *this ) ); @@ -960,9 +960,9 @@ inline QuatSlice& using Right = If_t< IsRestricted_v, CompositeType_t, const AT2& >; Right right( ~rhs ); - if( !tryAddAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); - } + //if( !tryAddAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + //} decltype(auto) left( derestrict( *this ) ); @@ -1012,9 +1012,9 @@ inline QuatSlice& using Right = If_t< IsRestricted_v, CompositeType_t, const AT2& >; Right right( ~rhs ); - if( !trySubAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); - } + //if( !trySubAssign( quaternion_, right, quat(), 0UL, 0UL, 0UL ) ) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + //} decltype(auto) left( derestrict( *this ) ); @@ -1065,9 +1065,9 @@ inline QuatSlice& BLAZE_THROW_INVALID_ARGUMENT( "Tensor sizes do not match" ); } - if( !trySchurAssign( quaternion_, (~rhs), quat(), 0UL, 0UL, 0UL ) ) { - BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); - } + //if( !trySchurAssign( quaternion_, (~rhs), quat(), 0UL, 0UL, 0UL ) ) { + // BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted quaternion" ); + //} decltype(auto) left( derestrict( *this ) ); @@ -1242,7 +1242,7 @@ inline size_t QuatSlice::nonZeros() const size_t count ( 0 ); for (size_t k = 0; k < pages(); ++k) { for (size_t i = 0; i < rows(); ++i) { - count += quaternion_.nonZeros( quat(), k, i ); + count += quaternion_.nonZeros( i, quat(), k); } } return count; diff --git a/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h b/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h index 2904526..64427c8 100644 --- a/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h +++ b/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h @@ -47,8 +47,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -94,7 +96,6 @@ class DenseGeneralTest void testAssignment(); void testAddAssign(); void testSubAssign(); - void testMultAssign(); void testSchurAssign(); void testScaling(); void testFunctionCall(); @@ -153,7 +154,7 @@ class DenseGeneralTest //**Member variables**************************************************************************** /*!\name Member variables */ //@{ - //AT quat_; //!< dynamic quaternion. + AT quat_; //!< dynamic quaternion. std::string test_; //!< Label of the currently performed test. //@} //********************************************************************************************** diff --git a/blazetest/src/mathtest/quatslice/CMakeLists.txt b/blazetest/src/mathtest/quatslice/CMakeLists.txt index 4c4b10e..8bb4194 100644 --- a/blazetest/src/mathtest/quatslice/CMakeLists.txt +++ b/blazetest/src/mathtest/quatslice/CMakeLists.txt @@ -34,6 +34,7 @@ set(category QuatSlice) set(tests IncludeTest + DenseGeneralTest ) foreach(test ${tests}) diff --git a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp index f42e1cb..219156f 100644 --- a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp +++ b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp @@ -74,18 +74,17 @@ namespace quatslice { // \exception std::runtime_error Operation error detected. */ DenseGeneralTest::DenseGeneralTest() - //: quat_ ( 3UL, 2UL, 5UL, 4UL ) + : quat_ ( 3UL, 2UL, 5UL, 4UL ) { testConstructors(); - //testAssignment(); - //testAddAssign(); - //testSubAssign(); - //testMultAssign(); - //testSchurAssign(); - //testScaling(); - //testFunctionCall(); - //testAt(); - //testIterator(); + testAssignment(); + testAddAssign(); + testSubAssign(); + testSchurAssign(); + testScaling(); + testFunctionCall(); + testAt(); + testIterator(); //testNonZeros(); //testReset(); //testClear(); @@ -123,116 +122,140 @@ void DenseGeneralTest::testConstructors() // quaternion tests //===================================================================================== - //{ - // test_ = "QuatSlice constructor (0x0)"; - - // AT quat; - - // // 0th quaternion quatslice - // try { - // blaze::quatslice( quat, 0UL ); - // } - // catch( std::invalid_argument& ) {} - //} - - //{ - // test_ = "QuatSlice constructor (2x0)"; - - // AT quat( 2UL, 2UL, 0UL ); - - // // 0th quaternion quatslice - // { - // RT quatslice0 = blaze::quatslice( quat, 0UL ); - - // checkRows ( quatslice0, 2UL ); - // checkColumns ( quatslice0, 0UL ); - // checkCapacity( quatslice0, 0UL ); - // checkNonZeros( quatslice0, 0UL ); - // } - - // // 1st quaternion quatslice - // { - // RT quatslice1 = blaze::quatslice( quat, 1UL ); - - // checkRows ( quatslice1, 2UL ); - // checkColumns ( quatslice1, 0UL ); - // checkCapacity( quatslice1, 0UL ); - // checkNonZeros( quatslice1, 0UL ); - // } - - // // 2nd quaternion quatslice - // try { - // blaze::quatslice( quat, 2UL ); - // } - // catch( std::invalid_argument& ) {} - //} - - //{ - // test_ = "QuatSlice constructor (5x4)"; - - // initialize(); - - // // 0th quaternion quatslice - // { - // RT quatslice0 = blaze::quatslice( quat_, 0UL ); - - // checkRows ( quatslice0, 5UL ); - // checkColumns ( quatslice0, 4UL ); - // checkCapacity( quatslice0, 20UL ); - // checkNonZeros( quatslice0, 10UL ); - - // if( quatslice0(0,0) != 0 || quatslice0(0,1) != 0 || quatslice0(0,2) != 0 || quatslice0(0,3) != 0 || - // quatslice0(1,0) != 0 || quatslice0(1,1) != 1 || quatslice0(1,2) != 0 || quatslice0(1,3) != 0 || - // quatslice0(2,0) != -2 || quatslice0(2,1) != 0 || quatslice0(2,2) != -3 || quatslice0(2,3) != 0 || - // quatslice0(3,0) != 0 || quatslice0(3,1) != 4 || quatslice0(3,2) != 5 || quatslice0(3,3) != -6 || - // quatslice0(4,0) != 7 || quatslice0(4,1) != -8 || quatslice0(4,2) != 9 || quatslice0(4,3) != 10 ) { - // std::ostringstream oss; - // oss << " Test: " << test_ << "\n" - // << " Error: Setup of 0th dense quatslice failed\n" - // << " Details:\n" - // << " Result:\n" << quatslice0 << "\n" - // << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - // throw std::runtime_error( oss.str() ); - // } - // } - - // // 1st quaternion quatslice - // { - // RT quatslice1 = blaze::quatslice( quat_, 1UL ); - - // checkRows ( quatslice1, 5UL ); - // checkColumns ( quatslice1, 4UL ); - // checkCapacity( quatslice1, 20UL ); - // checkNonZeros( quatslice1, 10UL ); - - // if( quatslice1(0,0) != 0 || quatslice1(0,1) != 0 || quatslice1(0,2) != 0 || quatslice1(0,3) != 0 || - // quatslice1(1,0) != 0 || quatslice1(1,1) != 1 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || - // quatslice1(2,0) != -2 || quatslice1(2,1) != 0 || quatslice1(2,2) != -3 || quatslice1(2,3) != 0 || - // quatslice1(3,0) != 0 || quatslice1(3,1) != 4 || quatslice1(3,2) != 5 || quatslice1(3,3) != -6 || - // quatslice1(4,0) != 7 || quatslice1(4,1) != -8 || quatslice1(4,2) != 9 || quatslice1(4,3) != 10 ) { - // std::ostringstream oss; - // oss << " Test: " << test_ << "\n" - // << " Error: Setup of 1st dense quatslice failed\n" - // << " Details:\n" - // << " Result:\n" << quatslice1 << "\n" - // << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; - // throw std::runtime_error( oss.str() ); - // } - // } - - // // 2nd quaternion quatslice - // try { - // RT quatslice2 = blaze::quatslice( quat_, 2UL ); - - // std::ostringstream oss; - // oss << " Test: " << test_ << "\n" - // << " Error: Out-of-bound quat access succeeded\n" - // << " Details:\n" - // << " Result:\n" << quatslice2 << "\n"; - // throw std::runtime_error( oss.str() ); - // } - // catch( std::invalid_argument& ) {} - //} + { + test_ = "QuatSlice constructor (0x0x0)"; + + AT quat; + + // 0th quaternion quatslice + try { + blaze::quatslice( quat, 0UL, 0UL ); + } + catch( std::invalid_argument& ) {} + } + + { + test_ = "QuatSlice constructor (3x4x0)"; + + AT quat( 2UL, 3UL, 4UL, 0UL ); + + // 0th quaternion quatslice + { + RT quatslice0 = blaze::quatslice( quat, 0UL ); + + checkPages ( quatslice0, 3UL ); + checkRows ( quatslice0, 4UL ); + checkColumns ( quatslice0, 0UL ); + checkCapacity( quatslice0, 0UL ); + checkNonZeros( quatslice0, 0UL ); + } + + // 1st quaternion quatslice + { + RT quatslice1 = blaze::quatslice( quat, 1UL ); + + checkPages ( quatslice1, 3UL ); + checkRows ( quatslice1, 4UL ); + checkColumns ( quatslice1, 0UL ); + checkCapacity( quatslice1, 0UL ); + checkNonZeros( quatslice1, 0UL ); + } + + // 2nd quaternion quatslice + try { + blaze::quatslice( quat, 2UL ); + } + catch( std::invalid_argument& ) {} + } + + { + test_ = "QuatSlice constructor (2x5x4)"; + + initialize(); + + // 0th quaternion quatslice + { + RT quatslice0 = blaze::quatslice( quat_, 0UL ); + + checkPages ( quatslice0, 2UL ); + checkRows ( quatslice0, 5UL ); + checkColumns ( quatslice0, 4UL ); + checkCapacity( quatslice0, 40UL ); + checkNonZeros( quatslice0, 20UL ); + + if( quatslice0(0,0,0) != 0 || quatslice0(0,0,1) != 0 || quatslice0(0,0,2) != 0 || quatslice0(0,0,3) != 0 || + quatslice0(0,1,0) != 0 || quatslice0(0,1,1) != 1 || quatslice0(0,1,2) != 0 || quatslice0(0,1,3) != 0 || + quatslice0(0,2,0) != -2 || quatslice0(0,2,1) != 0 || quatslice0(0,2,2) != -3 || quatslice0(0,2,3) != 0 || + quatslice0(0,3,0) != 0 || quatslice0(0,3,1) != 4 || quatslice0(0,3,2) != 5 || quatslice0(0,3,3) != -6 || + quatslice0(0,4,0) != 7 || quatslice0(0,4,1) != -8 || quatslice0(0,4,2) != 9 || quatslice0(0,4,3) != 10 || + quatslice0(1,0,0) != 0 || quatslice0(1,0,1) != 0 || quatslice0(1,0,2) != 0 || quatslice0(1,0,3) != 0 || + quatslice0(1,1,0) != 0 || quatslice0(1,1,1) != 1 || quatslice0(1,1,2) != 0 || quatslice0(1,1,3) != 0 || + quatslice0(1,2,0) != -2 || quatslice0(1,2,1) != 0 || quatslice0(1,2,2) != 13 || quatslice0(1,2,3) != 0 || + quatslice0(1,3,0) != 0 || quatslice0(1,3,1) != 4 || quatslice0(1,3,2) != 5 || quatslice0(1,3,3) != -6 || + quatslice0(1,4,0) != 7 || quatslice0(1,4,1) != -8 || quatslice0(1,4,2) != 9 || quatslice0(1,4,3) != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of 0th dense quatslice failed\n" + << " Details:\n" + << " Result:\n" + << quatslice0 << "\n" + << " Expected result:\n(( 0 0 0 0 ) ( 0 1 0 " + " 0 ) ( -2 0 -3 0 ) ( 0 4 5 -6 ) ( " + " 7 -8 9 10 ) )\n(( 0 0 0 0 ) ( 0 " + "1 0 0 ) ( -2 0 13 0 ) ( 0 4 5 " + "-6 ) ( 7 -8 9 10 ) )\n"; + throw std::runtime_error( oss.str() ); + } + } + + // 1st quaternion quatslice + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 5 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -8 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of 1st dense quatslice failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n(( 0 1 0 0 ) ( 0 0 " + "0 0 ) ( 0 12 -3 0 ) ( 0 4 5 -6 " + ") ( 7 28 9 10 ) )\n(( 0 0 0 0 ) ( " + " 0 1 0 0 ) ( -2 0 0 0 ) ( -3 4 5 " + " 33 ) ( 7 -8 9 11 ) )\n"; + throw std::runtime_error( oss.str() ); + } + } + + // 3rd quaternion quatslice + try { + RT quatslice3 = blaze::quatslice( quat_, 3UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Out-of-bound quat access succeeded\n" + << " Details:\n" + << " Result:\n" << quatslice3 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } } //************************************************************************************************* @@ -245,3305 +268,2705 @@ void DenseGeneralTest::testConstructors() // This function performs a test of all assignment operators of the QuatSlice specialization. // In case an error is detected, a \a std::runtime_error exception is thrown. */ -//void DenseGeneralTest::testAssignment() -//{ -// //===================================================================================== -// // homogeneous assignment -// //===================================================================================== -// -// { -// test_ = "QuatSlice homogeneous assignment"; -// -// initialize(); -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// quatslice1 = 8; -// -// -// checkRows ( quatslice1, 5UL ); -// checkColumns ( quatslice1, 4UL ); -// checkCapacity( quatslice1, 20UL ); -// checkNonZeros( quatslice1, 20UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 30UL ); -// -// if( quatslice1(0,0) != 8 || quatslice1(0,1) != 8 || quatslice1(0,2) != 8 || quatslice1(0,3) != 8 || -// quatslice1(1,0) != 8 || quatslice1(1,1) != 8 || quatslice1(1,2) != 8 || quatslice1(1,3) != 8 || -// quatslice1(2,0) != 8 || quatslice1(2,1) != 8 || quatslice1(2,2) != 8 || quatslice1(2,3) != 8 || -// quatslice1(3,0) != 8 || quatslice1(3,1) != 8 || quatslice1(3,2) != 8 || quatslice1(3,3) != 8 || -// quatslice1(4,0) != 8 || quatslice1(4,1) != 8 || quatslice1(4,2) != 8 || quatslice1(4,3) != 8 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice1 << "\n" -// << " Expected result:\n(( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 8 || quat_(1,0,1) != 8 || quat_(1,0,2) != 8 || quat_(1,0,3) != 8 || -// quat_(1,1,0) != 8 || quat_(1,1,1) != 8 || quat_(1,1,2) != 8 || quat_(1,1,3) != 8 || -// quat_(1,2,0) != 8 || quat_(1,2,1) != 8 || quat_(1,2,2) != 8 || quat_(1,2,3) != 8 || -// quat_(1,3,0) != 8 || quat_(1,3,1) != 8 || quat_(1,3,2) != 8 || quat_(1,3,3) != 8 || -// quat_(1,4,0) != 8 || quat_(1,4,1) != 8 || quat_(1,4,2) != 8 || quat_(1,4,3) != 8 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 8 8 8 8 )\n" -// " ( 8 8 8 8 )\n" -// " ( 8 8 8 8 )\n" -// " ( 8 8 8 8 )\n" -// " ( 8 8 8 8 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +void DenseGeneralTest::testAssignment() +{ + //===================================================================================== + // homogeneous assignment + //===================================================================================== + + { + test_ = "QuatSlice homogeneous assignment"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + quatslice1 = 8; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 40UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 8 || quatslice1(0,0,1) != 8 || quatslice1(0,0,2) != 8 || quatslice1(0,0,3) != 8 || + quatslice1(0,1,0) != 8 || quatslice1(0,1,1) != 8 || quatslice1(0,1,2) != 8 || quatslice1(0,1,3) != 8 || + quatslice1(0,2,0) != 8 || quatslice1(0,2,1) != 8 || quatslice1(0,2,2) != 8 || quatslice1(0,2,3) != 8 || + quatslice1(0,3,0) != 8 || quatslice1(0,3,1) != 8 || quatslice1(0,3,2) != 8 || quatslice1(0,3,3) != 8 || + quatslice1(0,4,0) != 8 || quatslice1(0,4,1) != 8 || quatslice1(0,4,2) != 8 || quatslice1(0,4,3) != 8 || + quatslice1(1,0,0) != 8 || quatslice1(1,0,1) != 8 || quatslice1(1,0,2) != 8 || quatslice1(1,0,3) != 8 || + quatslice1(1,1,0) != 8 || quatslice1(1,1,1) != 8 || quatslice1(1,1,2) != 8 || quatslice1(1,1,3) != 8 || + quatslice1(1,2,0) != 8 || quatslice1(1,2,1) != 8 || quatslice1(1,2,2) != 8 || quatslice1(1,2,3) != 8 || + quatslice1(1,3,0) != 8 || quatslice1(1,3,1) != 8 || quatslice1(1,3,2) != 8 || quatslice1(1,3,3) != 8 || + quatslice1(1,4,0) != 8 || quatslice1(1,4,1) != 8 || quatslice1(1,4,2) != 8 || quatslice1(1,4,3) != 8) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 )\n( 8 8 8 8 ))\n"; + throw std::runtime_error( oss.str() ); + } + + + if( quat_(0,0,0,0) != 0 || quat_(0,0,0,1) != 0 || quat_(0,0,0,2) != 0 || quat_(0,0,0,3) != 0 || + quat_(0,0,1,0) != 0 || quat_(0,0,1,1) != 1 || quat_(0,0,1,2) != 0 || quat_(0,0,1,3) != 0 || + quat_(0,0,2,0) != -2 || quat_(0,0,2,1) != 0 || quat_(0,0,2,2) != -3 || quat_(0,0,2,3) != 0 || + quat_(0,0,3,0) != 0 || quat_(0,0,3,1) != 4 || quat_(0,0,3,2) != 5 || quat_(0,0,3,3) != -6 || + quat_(0,0,4,0) != 7 || quat_(0,0,4,1) != -8 || quat_(0,0,4,2) != 9 || quat_(0,0,4,3) != 10 || + quat_(0,1,0,0) != 0 || quat_(0,1,0,1) != 0 || quat_(0,1,0,2) != 0 || quat_(0,1,0,3) != 0 || + quat_(0,1,1,0) != 0 || quat_(0,1,1,1) != 1 || quat_(0,1,1,2) != 0 || quat_(0,1,1,3) != 0 || + quat_(0,1,2,0) != -2 || quat_(0,1,2,1) != 0 || quat_(0,1,2,2) != 13 || quat_(0,1,2,3) != 0 || + quat_(0,1,3,0) != 0 || quat_(0,1,3,1) != 4 || quat_(0,1,3,2) != 5 || quat_(0,1,3,3) != -6 || + quat_(0,1,4,0) != 7 || quat_(0,1,4,1) != -8 || quat_(0,1,4,2) != 9 || quat_(0,1,4,3) != 10 || + quat_(1,0,0,0) != 8 || quat_(1,0,0,1) != 8 || quat_(1,0,0,2) != 8 || quat_(1,0,0,3) != 8 || + quat_(1,0,1,0) != 8 || quat_(1,0,1,1) != 8 || quat_(1,0,1,2) != 8 || quat_(1,0,1,3) != 8 || + quat_(1,0,2,0) != 8 || quat_(1,0,2,1) != 8 || quat_(1,0,2,2) != 8 || quat_(1,0,2,3) != 8 || + quat_(1,0,3,0) != 8 || quat_(1,0,3,1) != 8 || quat_(1,0,3,2) != 8 || quat_(1,0,3,3) != 8 || + quat_(1,0,4,0) != 8 || quat_(1,0,4,1) != 8 || quat_(1,0,4,2) != 8 || quat_(1,0,4,3) != 8 || + quat_(1,1,0,0) != 8 || quat_(1,1,0,1) != 8 || quat_(1,1,0,2) != 8 || quat_(1,1,0,3) != 8 || + quat_(1,1,1,0) != 8 || quat_(1,1,1,1) != 8 || quat_(1,1,1,2) != 8 || quat_(1,1,1,3) != 8 || + quat_(1,1,2,0) != 8 || quat_(1,1,2,1) != 8 || quat_(1,1,2,2) != 8 || quat_(1,1,2,3) != 8 || + quat_(1,1,3,0) != 8 || quat_(1,1,3,1) != 8 || quat_(1,1,3,2) != 8 || quat_(1,1,3,3) != 8 || + quat_(1,1,4,0) != 8 || quat_(1,1,4,1) != 8 || quat_(1,1,4,2) != 8 || quat_(1,1,4,3) != 8) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n(((( 0 0 0 0 )( 0 1 0 " + "0 )( -2 0 -3 0 )( 0 4 5 -6 )( 7 -8 " + "9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( 0 4 " + "5 -6 )( 7 -8 9 10 )))((( 8 8 8 8 )( " + " 8 8 8 8 )( 8 8 8 8 )( 8 8 8 8 )( " + "8 8 8 8 ))(( 8 8 8 8 )( 8 8 8 8 )( 8 " + " 8 8 8 )( 8 8 8 8 )( 8 8 8 8 )))"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // list assignment + //===================================================================================== + + { + test_ = "initializer list assignment (complete list)"; + + initialize(); + + RT quatslice3 = blaze::quatslice( quat_, 1UL ); + quatslice3 = {{{1, 2, 3, 4}, {7, 8, 9, 10}, {11, 12, 13, 14}, + {17, 18, 19, 20}, {21, 22, 23, 24}}, + {{-1, -2, -3, -4}, {-7, -8, -9, -10}, {-11, -12, -13, -14}, + {-17, -18, -19, -20}, {-21, -22, -23, -24}}}; + + + checkPages ( quatslice3, 2UL ); + checkRows ( quatslice3, 5UL ); + checkColumns ( quatslice3, 4UL ); + checkCapacity( quatslice3, 40UL ); + checkNonZeros( quatslice3, 40UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice3(0,0,0) != 1 || quatslice3(0,0,1) != 2 || quatslice3(0,0,2) != 3 || quatslice3(0,0,3) != 4 || + quatslice3(0,1,0) != 7 || quatslice3(0,1,1) != 8 || quatslice3(0,1,2) != 9 || quatslice3(0,1,3) != 10 || + quatslice3(0,2,0) != 11 || quatslice3(0,2,1) != 12 || quatslice3(0,2,2) != 13 || quatslice3(0,2,3) != 14 || + quatslice3(0,3,0) != 17 || quatslice3(0,3,1) != 18 || quatslice3(0,3,2) != 19 || quatslice3(0,3,3) != 20 || + quatslice3(0,4,0) != 21 || quatslice3(0,4,1) != 22 || quatslice3(0,4,2) != 23 || quatslice3(0,4,3) != 24 || + quatslice3(1,0,0) != -1 || quatslice3(1,0,1) != -2 || quatslice3(1,0,2) != -3 || quatslice3(1,0,3) != -4 || + quatslice3(1,1,0) != -7 || quatslice3(1,1,1) != -8 || quatslice3(1,1,2) != -9 || quatslice3(1,1,3) != -10 || + quatslice3(1,2,0) != -11 || quatslice3(1,2,1) != -12 || quatslice3(1,2,2) != -13 || quatslice3(1,2,3) != -14 || + quatslice3(1,3,0) != -17 || quatslice3(1,3,1) != -18 || quatslice3(1,3,2) != -19 || quatslice3(1,3,3) != -20 || + quatslice3(1,4,0) != -21 || quatslice3(1,4,1) != -22 || quatslice3(1,4,2) != -23 || quatslice3(1,4,3) != -24) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice3 << "\n" + << " Expected result:\n((( 1 2 3 4 )( 7 8 9 " + " 10 )( 11 12 13 14 )( 17 18 19 " + "20 )( 21 22 23 24 ))(( -1 -2 -3 " + "-4 )( -7 -8 -9 -10 )( -11 -12 -13 " + "-14 )( -17 -18 -19 -20 )( -21 -22 -23 " + "-24 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 1 || quat_(1,0,0,1) != 2 || quat_(1,0,0,2) != 3 || quat_(1,0,0,3) != 4 || + quat_(1,0,1,0) != 7 || quat_(1,0,1,1) != 8 || quat_(1,0,1,2) != 9 || quat_(1,0,1,3) != 10 || + quat_(1,0,2,0) != 11 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != 13 || quat_(1,0,2,3) != 14 || + quat_(1,0,3,0) != 17 || quat_(1,0,3,1) != 18 || quat_(1,0,3,2) != 19 || quat_(1,0,3,3) != 20 || + quat_(1,0,4,0) != 21 || quat_(1,0,4,1) != 22 || quat_(1,0,4,2) != 23 || quat_(1,0,4,3) != 24 || + quat_(1,1,0,0) != -1 || quat_(1,1,0,1) != -2 || quat_(1,1,0,2) != -3 || quat_(1,1,0,3) != -4 || + quat_(1,1,1,0) != -7 || quat_(1,1,1,1) != -8 || quat_(1,1,1,2) != -9 || quat_(1,1,1,3) != -10 || + quat_(1,1,2,0) != -11 || quat_(1,1,2,1) != -12 || quat_(1,1,2,2) != -13 || quat_(1,1,2,3) != -14 || + quat_(1,1,3,0) != -17 || quat_(1,1,3,1) != -18 || quat_(1,1,3,2) != -19 || quat_(1,1,3,3) != -20 || + quat_(1,1,4,0) != -21 || quat_(1,1,4,1) != -22 || quat_(1,1,4,2) != -23 || quat_(1,1,4,3) != -24 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n((( 1 2 3 4 )( 7 8 9 " + " 10 )( 11 12 13 14 )( 17 18 19 " + "20 )( 21 22 23 24 ))(( -1 -2 -3 " + "-4 )( -7 -8 -9 -10 )( -11 -12 -13 " + "-14 )( -17 -18 -19 -20 )( -21 -22 -23 " + "-24 )))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "initializer list assignment (incomplete list)"; + + initialize(); + + RT quatslice3 = blaze::quatslice( quat_, 1UL ); + quatslice3 = {{{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}}, + {{-1, -2}, {-1, -2}, {-1, -2}, {-1, -2}, {-1, -2}}}; + + checkPages ( quatslice3, 2UL ); + checkRows ( quatslice3, 5UL ); + checkColumns ( quatslice3, 4UL ); + checkCapacity( quatslice3, 40UL ); + checkNonZeros( quatslice3, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice3(0,0,0) != 1 || quatslice3(0,0,1) != 2 || quatslice3(0,0,2) != 0 || quatslice3(0,0,3) != 0 || + quatslice3(0,1,0) != 1 || quatslice3(0,1,1) != 2 || quatslice3(0,1,2) != 0 || quatslice3(0,1,3) != 0 || + quatslice3(0,2,0) != 1 || quatslice3(0,2,1) != 2 || quatslice3(0,2,2) != 0 || quatslice3(0,2,3) != 0 || + quatslice3(0,3,0) != 1 || quatslice3(0,3,1) != 2 || quatslice3(0,3,2) != 0 || quatslice3(0,3,3) != 0 || + quatslice3(0,4,0) != 1 || quatslice3(0,4,1) != 2 || quatslice3(0,4,2) != 0 || quatslice3(0,4,3) != 0 || + quatslice3(1,0,0) != -1 || quatslice3(1,0,1) != -2 || quatslice3(1,0,2) != 0 || quatslice3(1,0,3) != 0 || + quatslice3(1,1,0) != -1 || quatslice3(1,1,1) != -2 || quatslice3(1,1,2) != 0 || quatslice3(1,1,3) != 0 || + quatslice3(1,2,0) != -1 || quatslice3(1,2,1) != -2 || quatslice3(1,2,2) != 0 || quatslice3(1,2,3) != 0 || + quatslice3(1,3,0) != -1 || quatslice3(1,3,1) != -2 || quatslice3(1,3,2) != 0 || quatslice3(1,3,3) != 0 || + quatslice3(1,4,0) != -1 || quatslice3(1,4,1) != -2 || quatslice3(1,4,2) != 0 || quatslice3(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice3 << "\n" + << " Expected result:\n((( 1 2 0 0 )( 1 2 0 " + "0 )( 1 2 0 0 )( 1 2 0 0 )( 1 2 0 " + " 0 ))(( -1 -2 0 0 )( -1 -2 0 0 )( -1 " + " -2 0 0 )( -1 -2 0 0 )( -1 -2 0 " + "0 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 1 || quat_(1,0,0,1) != 2 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 1 || quat_(1,0,1,1) != 2 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 1 || quat_(1,0,2,1) != 2 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 1 || quat_(1,0,3,1) != 2 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 1 || quat_(1,0,4,1) != 2 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != -1 || quat_(1,1,0,1) != -2 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != -1 || quat_(1,1,1,1) != -2 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != -1 || quat_(1,1,2,1) != -2 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -1 || quat_(1,1,3,1) != -2 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 0 || + quat_(1,1,4,0) != -1 || quat_(1,1,4,1) != -2 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n((( 1 2 0 0 )( 1 2 0 " + "0 )( 1 2 0 0 )( 1 2 0 0 )( 1 2 0 " + " 0 ))(( -1 -2 0 0 )( -1 -2 0 0 )( -1 " + " -2 0 0 )( -1 -2 0 0 )( -1 -2 0 " + "0 )))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // copy assignment + //===================================================================================== + + { + test_ = "QuatSlice copy assignment"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 0UL ); + quatslice1 = 0; + quatslice1 = blaze::quatslice( quat_, 1UL ); + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 5 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -8 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 1 0 0 ) ( 0 0 " + "0 0 ) ( 0 12 -3 0 ) ( 0 4 5 -6 " + ") ( 7 28 9 10 ) )\n(( 0 0 0 0 ) ( " + " 0 1 0 0 ) ( -2 0 0 0 ) ( -3 4 5 " + " 33 ) ( 7 -8 9 11 ) )\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(0,0,0,0) != 0 || quat_(0,0,0,1) != 1 || quat_(0,0,0,2) != 0 || quat_(0,0,0,3) != 0 || + quat_(0,0,1,0) != 0 || quat_(0,0,1,1) != 0 || quat_(0,0,1,2) != 0 || quat_(0,0,1,3) != 0 || + quat_(0,0,2,0) != 0 || quat_(0,0,2,1) != 12 || quat_(0,0,2,2) != -3 || quat_(0,0,2,3) != 0 || + quat_(0,0,3,0) != 0 || quat_(0,0,3,1) != 4 || quat_(0,0,3,2) != 5 || quat_(0,0,3,3) != -6 || + quat_(0,0,4,0) != 7 || quat_(0,0,4,1) != 28 || quat_(0,0,4,2) != 9 || quat_(0,0,4,3) != 10 || + quat_(0,1,0,0) != 0 || quat_(0,1,0,1) != 0 || quat_(0,1,0,2) != 0 || quat_(0,1,0,3) != 0 || + quat_(0,1,1,0) != 0 || quat_(0,1,1,1) != 1 || quat_(0,1,1,2) != 0 || quat_(0,1,1,3) != 0 || + quat_(0,1,2,0) != -2 || quat_(0,1,2,1) != 0 || quat_(0,1,2,2) != 0 || quat_(0,1,2,3) != 0 || + quat_(0,1,3,0) != -3 || quat_(0,1,3,1) != 4 || quat_(0,1,3,2) != 5 || quat_(0,1,3,3) != 33 || + quat_(0,1,4,0) != 7 || quat_(0,1,4,1) != -8 || quat_(0,1,4,2) != 9 || quat_(0,1,4,3) != 11 || + quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 0 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 0 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != -3 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 4 || quat_(1,0,3,2) != 5 || quat_(1,0,3,3) != -6 || + quat_(1,0,4,0) != 7 || quat_(1,0,4,1) != 28 || quat_(1,0,4,2) != 9 || quat_(1,0,4,3) != 10 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 1 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != -2 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 4 || quat_(1,1,3,2) != 5 || quat_(1,1,3,3) != 33 || + quat_(1,1,4,0) != 7 || quat_(1,1,4,1) != -8 || quat_(1,1,4,2) != 9 || quat_(1,1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n(( 0 1 0 0 ) ( 0 0 " + "0 0 ) ( 0 12 -3 0 ) ( 0 4 5 -6 " + ") ( 7 28 9 10 ) )\n(( 0 0 0 0 ) ( " + " 0 1 0 0 ) ( -2 0 0 0 ) ( -3 4 5 " + " 33 ) ( 7 -8 9 11 ) )\n(( 0 1 0 0 ) " + "( 0 0 0 0 ) ( 0 12 -3 0 ) ( 0 4 5 " + "-6 ) ( 7 28 9 10 ) )\n(( 0 0 0 0 ) ( " + " 0 1 0 0 ) ( -2 0 0 0 ) ( -3 4 5 " + " 33 ) ( 7 -8 9 11 ) )\n((( 0 0 0 0 " + ")( 0 1 0 0 )( -2 0 -3 4 )( 0 0 5 " + " 2 )( 7 -8 9 10 ))(( 0 0 0 0 )( " + "0 1 0 0 )( 62 0 -3 0 )( 0 5 15 " + "16 )( -7 -8 19 10 ))))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense quaternion assignment + //===================================================================================== + + { + test_ = "dense quaternion assignment "; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + blaze::DynamicTensor t1; + t1 = {{{0, 8, 0, 9}, {0}, {0}, {0}, {0}}, + {{7, 8, 10, 9}, {1}, {1}, {1}, {1}}}; + + quatslice1 = t1; + + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 10UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 8 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 9 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 0 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 0 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 7 || quatslice1(1,0,1) != 8 || quatslice1(1,0,2) != 10 || quatslice1(1,0,3) != 9 || + quatslice1(1,1,0) != 1 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != 1 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != 1 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 0 || + quatslice1(1,4,0) != 1 || quatslice1(1,4,1) != 0 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 0 ) { + std::ostringstream oss; + oss + << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n((( 0 8 0 9 )( 0 0 0 " + " 0 )( 0 0 0 0 )( 0 0 0 0 )( 0 0 " + "0 0 ))(( 7 8 10 9 )( 1 0 0 0 )( 1 " + "0 0 0 )( 1 0 0 0 )( 1 0 0 0 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 8 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 9 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 0 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 0 || quat_(1,0,2,1) != 0 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 0 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 7 || quat_(1,1,0,1) != 8 || quat_(1,1,0,2) != 10 || quat_(1,1,0,3) != 9 || + quat_(1,1,1,0) != 1 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 1 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != 1 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 0 || + quat_(1,1,4,0) != 1 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n(((( 0 0 0 0 )( 0 1 0 0 " + ")( -2 0 -3 0 )( 0 4 5 -6 )( 7 " + " -8 9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( " + "-2 0 13 0 )( 0 4 5 -6 )( 7 -8 9 " + " 10 )))((( 0 8 0 9 )( 0 0 0 0 )( 0 " + "0 0 0 )( 0 0 0 0 )( 0 0 0 0 ))(( 7 8 " + " 10 9 )( 1 0 0 0 )( 1 0 0 0 )( 1 0 " + "0 0 )( 1 0 0 0 )))((( 0 0 0 0 )( 0 1 " + "0 0 )( -2 0 -3 4 )( 0 0 5 2 )( 7 " + " -8 9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( " + "62 0 -3 0 )( 0 5 15 16 )( -7 " + "-8 19 10 ))))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + { + test_ = "dense quaternion assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + using AlignedPadded = blaze::CustomTensor; + std::unique_ptr memory( blaze::allocate( 160UL ) ); + AlignedPadded m1( memory.get(), 2UL, 5UL, 4UL, 16UL ); + m1 = 0; + m1(0,0,0) = 10; + m1(0,0,1) = 8; + m1(0,0,2) = 7; + m1(0,0,3) = 9; + m1(1,1,3) = 6; + + quatslice1 = m1; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL); + checkNonZeros( quatslice1, 5UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 10 || quatslice1(0,0,1) != 8 || quatslice1(0,0,2) != 7 || quatslice1(0,0,3) != 9 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 0 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 0 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 6 || + quatslice1(1,2,0) != 0 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != 0 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 0 || + quatslice1(1,4,0) != 0 || quatslice1(1,4,1) != 0 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 0) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n((( 10 8 7 9 )( 0 0 0 0 " + ")( 0 0 0 0 )( 0 0 0 0 )( 0 0 0 0 ))(( " + " 0 0 0 0 )( 0 0 0 6 )( 0 0 0 0 )( " + "0 0 0 0 )( 0 0 0 0 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 10 || quat_(1,0,0,1) != 8 || quat_(1,0,0,2) != 7 || quat_(1,0,0,3) != 9 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 0 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 0 || quat_(1,0,2,1) != 0 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 0 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 6 || + quat_(1,1,2,0) != 0 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != 0 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 0 || + quat_(1,1,4,0) != 0 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 0) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n(((( 0 0 0 0 )( 0 1 0 0 " + ")( -2 0 -3 0 )( 0 4 5 -6 )( 7 " + " -8 9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( " + "-2 0 13 0 )( 0 4 5 -6 )( 7 -8 9 " + " 10 )))((( 10 8 7 9 )( 0 0 0 0 )( 0 " + "0 0 0 )( 0 0 0 0 )( 0 0 0 0 ))(( 0 0 " + "0 0 )( 0 0 0 6 )( 0 0 0 0 )( 0 0 0 0 " + ")( 0 0 0 0 )))((( 0 0 0 0 )( 0 1 0 0 " + ")( -2 0 -3 4 )( 0 0 5 2 )( 7 -8 " + "9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( 62 " + "0 -3 0 )( 0 5 15 16 )( -7 -8 " + " 19 10 ))))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense quaternion assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + using UnalignedUnpadded = blaze::CustomTensor; + std::unique_ptr memory( new int[41] ); + UnalignedUnpadded m1( memory.get()+1UL, 2UL, 5UL, 4UL ); + m1 = 0; + m1(0,0,0) = 10; + m1(0,0,1) = 8; + m1(0,0,2) = 7; + m1(0,0,3) = 9; + m1(1,1,3) = 6; + + quatslice1 = m1; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL); + checkNonZeros( quatslice1, 5UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 10 || quatslice1(0,0,1) != 8 || quatslice1(0,0,2) != 7 || quatslice1(0,0,3) != 9 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 0 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 0 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 6 || + quatslice1(1,2,0) != 0 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != 0 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 0 || + quatslice1(1,4,0) != 0 || quatslice1(1,4,1) != 0 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 0) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n((( 10 8 7 9 )( 0 0 0 0 " + ")( 0 0 0 0 )( 0 0 0 0 )( 0 0 0 0 ))(( " + " 0 0 0 0 )( 0 0 0 6 )( 0 0 0 0 )( " + "0 0 0 0 )( 0 0 0 0 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 10 || quat_(1,0,0,1) != 8 || quat_(1,0,0,2) != 7 || quat_(1,0,0,3) != 9 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 0 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 0 || quat_(1,0,2,1) != 0 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 0 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 6 || + quat_(1,1,2,0) != 0 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != 0 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 0 || + quat_(1,1,4,0) != 0 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 0) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n(((( 0 0 0 0 )( 0 1 0 0 " + ")( -2 0 -3 0 )( 0 4 5 -6 )( 7 " + " -8 9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( " + "-2 0 13 0 )( 0 4 5 -6 )( 7 -8 9 " + " 10 )))((( 10 8 7 9 )( 0 0 0 0 )( 0 " + "0 0 0 )( 0 0 0 0 )( 0 0 0 0 ))(( 0 0 " + "0 0 )( 0 0 0 6 )( 0 0 0 0 )( 0 0 0 0 " + ")( 0 0 0 0 )))((( 0 0 0 0 )( 0 1 0 0 " + ")( -2 0 -3 4 )( 0 0 5 2 )( 7 -8 " + "9 10 ))(( 0 0 0 0 )( 0 1 0 0 )( 62 " + "0 -3 0 )( 0 5 15 16 )( -7 -8 " + " 19 10 ))))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the QuatSlice addition assignment operators. // +// \return void +// \exception std::runtime_error Error detected. // -// //===================================================================================== -// // list assignment -// //===================================================================================== +// This function performs a test of the addition assignment operators of the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testAddAssign() +{ + //===================================================================================== + // QuatSlice addition assignment + //===================================================================================== + + { + test_ = "QuatSlice addition assignment"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + quatslice1 += blaze::quatslice( quat_, 0UL ); + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 23UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -6 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 8 || quatslice1(0,3,2) != 10 || quatslice1(0,3,3) != -12 || + quatslice1(0,4,0) != 14 || quatslice1(0,4,1) != 20 || quatslice1(0,4,2) != 18 || quatslice1(0,4,3) != 20 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 2 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -4 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 13 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 8 || quatslice1(1,3,2) != 10 || quatslice1(1,3,3) != 27 || + quatslice1(1,4,0) != 14 || quatslice1(1,4,1) != -16 || quatslice1(1,4,2) != 18 || quatslice1(1,4,3) != 21) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n((( 0 1 0 0 )( 0 1 0 0 )( -2 " + " 12 -6 0 )( 0 8 10 -12 )( 14 20 " + " 18 20 ))(( 0 0 0 0 )( 0 2 0 0 )( -4 0 " + "13 0 )( -3 8 10 27 )( 14 -16 18 " + "21 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 1 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != -2 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != -6 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 8 || quat_(1,0,3,2) != 10 || quat_(1,0,3,3) != -12 || + quat_(1,0,4,0) != 14 || quat_(1,0,4,1) != 20 || quat_(1,0,4,2) != 18 || quat_(1,0,4,3) != 20 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 2 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != -4 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 13 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 8 || quat_(1,1,3,2) != 10 || quat_(1,1,3,3) != 27 || + quat_(1,1,4,0) != 14 || quat_(1,1,4,1) != -16 || quat_(1,1,4,2) != 18 || quat_(1,1,4,3) != 21) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" + << quat_ << "\n" + << " Expected result:\n((( 0 1 0 0 )( 0 1 0 0 )( -2 " + " 12 -6 0 )( 0 8 10 -12 )( 14 20 " + " 18 20 ))(( 0 0 0 0 )( 0 2 0 0 )( -4 0 " + "13 0 )( -3 8 10 27 )( 14 -16 18 21 " + ")))\n"; + throw std::runtime_error( oss.str() ); + } + + } + + //===================================================================================== + // dense quaternion addition assignment + //===================================================================================== + + { + test_ = "dense quaternion addition assignment (mixed type)"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + const blaze::DynamicTensor< short > t{ + {{0, 0, 0, 0}, {0, 1, 0, 0}, {-2, 0, -3, 0}, {0, 4, 5, -6}, + {7, -8, 9, 10}}, + {{0, 0, 0, 0}, {0, 1, 0, 0}, {-2, 0, -3, 0}, {0, 4, 5, -6}, + {7, -8, 9, 10}}}; + + quatslice1 += t; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 23UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -6 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 8 || quatslice1(0,3,2) != 10 || quatslice1(0,3,3) != -12 || + quatslice1(0,4,0) != 14 || quatslice1(0,4,1) != 20 || quatslice1(0,4,2) != 18 || quatslice1(0,4,3) != 20 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 2 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -4 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != -3 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 8 || quatslice1(1,3,2) != 10 || quatslice1(1,3,3) != 27 || + quatslice1(1,4,0) != 14 || quatslice1(1,4,1) != -16 || quatslice1(1,4,2) != 18 || quatslice1(1,4,3) != 21 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 1 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != -2 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != -6 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 8 || quat_(1,0,3,2) != 10 || quat_(1,0,3,3) != -12 || + quat_(1,0,4,0) != 14 || quat_(1,0,4,1) != 20 || quat_(1,0,4,2) != 18 || quat_(1,0,4,3) != 20 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 2 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != -4 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != -3 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 8 || quat_(1,1,3,2) != 10 || quat_(1,1,3,3) != 27 || + quat_(1,1,4,0) != 14 || quat_(1,1,4,1) != -16 || quat_(1,1,4,2) != 18 || quat_(1,1,4,3) != 21 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense quaternion addition assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + using AlignedPadded = blaze::CustomTensor; + std::unique_ptr memory( blaze::allocate( 160UL ) ); + AlignedPadded m( memory.get(), 2UL, 5UL, 4UL, 16UL ); + m(0,0,0) = 0; + m(0,0,1) = 0; + m(0,0,2) = 0; + m(0,0,3) = 13; + m(0,1,0) = 0; + m(0,1,1) = 1; + m(0,1,2) = 0; + m(0,1,3) = 0; + m(0,2,0) = -2; + m(0,2,1) = 0; + m(0,2,2) = -3; + m(0,2,3) = 0; + m(0,3,0) = 0; + m(0,3,1) = 4; + m(0,3,2) = 5; + m(0,3,3) = -6; + m(0,4,0) = 7; + m(0,4,1) = -8; + m(0,4,2) = 9; + m(0,4,3) = 10; + m(1,0,0) = 0; + m(1,0,1) = 0; + m(1,0,2) = 0; + m(1,0,3) = 0; + m(1,1,0) = 0; + m(1,1,1) = 1; + m(1,1,2) = 0; + m(1,1,3) = 0; + m(1,2,0) = 33; + m(1,2,1) = 0; + m(1,2,2) = -3; + m(1,2,3) = 0; + m(1,3,0) = 0; + m(1,3,1) = 4; + m(1,3,2) = 5; + m(1,3,3) = -6; + m(1,4,0) = 17; + m(1,4,1) = 18; + m(1,4,2) = 9; + m(1,4,3) = 10; + + quatslice1 += m; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL); + checkNonZeros( quatslice1, 24UL); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 13 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -6 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 8 || quatslice1(0,3,2) != 10 || quatslice1(0,3,3) != -12 || + quatslice1(0,4,0) != 14 || quatslice1(0,4,1) != 20 || quatslice1(0,4,2) != 18 || quatslice1(0,4,3) != 20 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 2 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != 31 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != -3 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 8 || quatslice1(1,3,2) != 10 || quatslice1(1,3,3) != 27 || + quatslice1(1,4,0) != 24 || quatslice1(1,4,1) != 10 || quatslice1(1,4,2) != 18 || quatslice1(1,4,3) != 21 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 13 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 1 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != -2 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != -6 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 8 || quat_(1,0,3,2) != 10 || quat_(1,0,3,3) != -12 || + quat_(1,0,4,0) != 14 || quat_(1,0,4,1) != 20 || quat_(1,0,4,2) != 18 || quat_(1,0,4,3) != 20 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 2 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 31 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != -3 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 8 || quat_(1,1,3,2) != 10 || quat_(1,1,3,3) != 27 || + quat_(1,1,4,0) != 24 || quat_(1,1,4,1) != 10 || quat_(1,1,4,2) != 18 || quat_(1,1,4,3) != 21 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense quaternion addition assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + using UnalignedUnpadded = blaze::CustomTensor; + std::unique_ptr memory( new int[41] ); + UnalignedUnpadded m( memory.get()+1UL, 2UL, 5UL, 4UL ); + m(0,0,0) = 0; + m(0,0,1) = 0; + m(0,0,2) = 0; + m(0,0,3) = 13; + m(0,1,0) = 0; + m(0,1,1) = 1; + m(0,1,2) = 0; + m(0,1,3) = 0; + m(0,2,0) = -2; + m(0,2,1) = 0; + m(0,2,2) = -3; + m(0,2,3) = 0; + m(0,3,0) = 0; + m(0,3,1) = 4; + m(0,3,2) = 5; + m(0,3,3) = -6; + m(0,4,0) = 7; + m(0,4,1) = -8; + m(0,4,2) = 9; + m(0,4,3) = 10; + m(1,0,0) = 0; + m(1,0,1) = 0; + m(1,0,2) = 0; + m(1,0,3) = 0; + m(1,1,0) = 0; + m(1,1,1) = 1; + m(1,1,2) = 0; + m(1,1,3) = 0; + m(1,2,0) = 33; + m(1,2,1) = 0; + m(1,2,2) = -3; + m(1,2,3) = 0; + m(1,3,0) = 0; + m(1,3,1) = 4; + m(1,3,2) = 5; + m(1,3,3) = -6; + m(1,4,0) = 17; + m(1,4,1) = 18; + m(1,4,2) = 9; + m(1,4,3) = 10; + + quatslice1 += m; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL); + checkNonZeros( quatslice1, 24UL); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 13 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -6 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 8 || quatslice1(0,3,2) != 10 || quatslice1(0,3,3) != -12 || + quatslice1(0,4,0) != 14 || quatslice1(0,4,1) != 20 || quatslice1(0,4,2) != 18 || quatslice1(0,4,3) != 20 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 2 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != 31 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != -3 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 8 || quatslice1(1,3,2) != 10 || quatslice1(1,3,3) != 27 || + quatslice1(1,4,0) != 24 || quatslice1(1,4,1) != 10 || quatslice1(1,4,2) != 18 || quatslice1(1,4,3) != 21 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 13 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 1 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != -2 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != -6 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 8 || quat_(1,0,3,2) != 10 || quat_(1,0,3,3) != -12 || + quat_(1,0,4,0) != 14 || quat_(1,0,4,1) != 20 || quat_(1,0,4,2) != 18 || quat_(1,0,4,3) != 20 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 2 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 31 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != -3 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 8 || quat_(1,1,3,2) != 10 || quat_(1,1,3,3) != 27 || + quat_(1,1,4,0) != 24 || quat_(1,1,4,1) != 10 || quat_(1,1,4,2) != 18 || quat_(1,1,4,3) != 21 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 2 0 0 )\n" + " ( -4 0 -6 0 )\n" + " ( 0 8 10 -12 )\n" + " ( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the QuatSlice subtraction assignment operators. // -// { -// test_ = "initializer list assignment (complete list)"; +// \return void +// \exception std::runtime_error Error detected. // -// initialize(); +// This function performs a test of the subtraction assignment operators of the QuatSlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testSubAssign() +{ + //===================================================================================== + // QuatSlice subtraction assignment + //===================================================================================== + + { + test_ = "QuatSlice subtraction assignment"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + quatslice1 -= blaze::quatslice( quat_, 0UL ); + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 9UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != -1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 36 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != 0 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) !=-13 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 39 || + quatslice1(1,4,0) != 0 || quatslice1(1,4,1) != 0 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 1) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n((( 0 1 0 0 )( 0 1 0 0 )( -2 " + " 12 -6 0 )( 0 8 10 -12 )( 14 20 " + " 18 20 ))(( 0 0 0 0 )( 0 2 0 0 )( -4 0 " + "13 0 )( -3 8 10 27 )( 14 -16 18 " + "21 )))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != -1 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 2 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 36 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 0 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) !=-13 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 39 || + quat_(1,1,4,0) != 0 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense quaternion subtraction assignment + //===================================================================================== + + { + test_ = "dense quaternion subtraction assignment (mixed type)"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + const blaze::DynamicTensor< short > t{ + {{0, 0, 0, 0}, {0, 1, 0, 0}, {-2, 0, -3, 0}, {0, 4, 5, -6}, + {7, -8, 9, 10}}, + {{0, 0, 0, 0}, {0, 1, 0, 0}, {-2, 0, -3, 0}, {0, 4, 5, -6}, + {7, -8, 9, 10}}}; + + quatslice1 -= t; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 9UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != -1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 36 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != 0 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 3 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 39 || + quatslice1(1,4,0) != 0 || quatslice1(1,4,1) != 0 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 1 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != -1 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 2 || quat_(1,0,2,1) != 12 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 36 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 0 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 3 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != -3 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 39 || + quat_(1,1,4,0) != 0 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + } + } + + { + test_ = "dense quaternion subtraction assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + using AlignedPadded = blaze::CustomTensor; + std::unique_ptr memory( blaze::allocate( 160UL ) ); + AlignedPadded m( memory.get(), 2UL, 5UL, 4UL, 16UL ); + m(0,0,0) = 0; + m(0,0,1) = 0; + m(0,0,2) = 0; + m(0,0,3) = 13; + m(0,1,0) = 0; + m(0,1,1) = 1; + m(0,1,2) = 0; + m(0,1,3) = 0; + m(0,2,0) = -2; + m(0,2,1) = 0; + m(0,2,2) = -3; + m(0,2,3) = 0; + m(0,3,0) = 0; + m(0,3,1) = 4; + m(0,3,2) = 5; + m(0,3,3) = -6; + m(0,4,0) = 7; + m(0,4,1) = -8; + m(0,4,2) = 9; + m(0,4,3) = 10; + m(1,0,0) = 0; + m(1,0,1) = 0; + m(1,0,2) = 0; + m(1,0,3) = 0; + m(1,1,0) = 0; + m(1,1,1) = 1; + m(1,1,2) = 0; + m(1,1,3) = 0; + m(1,2,0) = 33; + m(1,2,1) = 0; + m(1,2,2) = -3; + m(1,2,3) = 0; + m(1,3,0) = 0; + m(1,3,1) = 4; + m(1,3,2) = 5; + m(1,3,3) = -6; + m(1,4,0) = 17; + m(1,4,1) = 18; + m(1,4,2) = 9; + m(1,4,3) = 10; + + quatslice1 -= m; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL); + checkNonZeros( quatslice1, 13UL); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != -13 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != -1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 36 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) !=-35 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 3 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 39 || + quatslice1(1,4,0) !=-10 || quatslice1(1,4,1) != -26 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense quaternion subtraction assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + using UnalignedUnpadded = blaze::CustomTensor; + std::unique_ptr memory( new int[41] ); + UnalignedUnpadded m( memory.get()+1UL, 2UL, 5UL, 4UL ); + m(0,0,0) = 0; + m(0,0,1) = 0; + m(0,0,2) = 0; + m(0,0,3) = 13; + m(0,1,0) = 0; + m(0,1,1) = 1; + m(0,1,2) = 0; + m(0,1,3) = 0; + m(0,2,0) = -2; + m(0,2,1) = 0; + m(0,2,2) = -3; + m(0,2,3) = 0; + m(0,3,0) = 0; + m(0,3,1) = 4; + m(0,3,2) = 5; + m(0,3,3) = -6; + m(0,4,0) = 7; + m(0,4,1) = -8; + m(0,4,2) = 9; + m(0,4,3) = 10; + m(1,0,0) = 0; + m(1,0,1) = 0; + m(1,0,2) = 0; + m(1,0,3) = 0; + m(1,1,0) = 0; + m(1,1,1) = 1; + m(1,1,2) = 0; + m(1,1,3) = 0; + m(1,2,0) = 33; + m(1,2,1) = 0; + m(1,2,2) = -3; + m(1,2,3) = 0; + m(1,3,0) = 0; + m(1,3,1) = 4; + m(1,3,2) = 5; + m(1,3,3) = -6; + m(1,4,0) = 17; + m(1,4,1) = 18; + m(1,4,2) = 9; + m(1,4,3) = 10; + + quatslice1 -= m; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL); + checkNonZeros( quatslice1, 13UL); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != -13 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != -1 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 2 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != 0 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 0 || quatslice1(0,3,2) != 0 || quatslice1(0,3,3) != 0 || + quatslice1(0,4,0) != 0 || quatslice1(0,4,1) != 36 || quatslice1(0,4,2) != 0 || quatslice1(0,4,3) != 0 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 0 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) !=-35 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 3 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 0 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 39 || + quatslice1(1,4,0) !=-10 || quatslice1(1,4,1) != -26 || quatslice1(1,4,2) != 0 || quatslice1(1,4,3) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the QuatSlice Schur product assignment operators. // -// RT quatslice3 = blaze::quatslice( quat_, 1UL ); -// quatslice3 = { -// {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} -// }; +// \return void +// \exception std::runtime_error Error detected. // -// checkRows ( quatslice3, 5UL ); -// checkColumns ( quatslice3, 4UL ); -// checkCapacity( quatslice3, 20UL ); -// checkNonZeros( quatslice3, 20UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 30UL ); -// -// if( quatslice3(0,0) != 1 || quatslice3(0,1) != 2 || quatslice3(0,2) != 3 || quatslice3(0,3) != 4 || -// quatslice3(1,0) != 1 || quatslice3(1,1) != 2 || quatslice3(1,2) != 3 || quatslice3(1,3) != 4 || -// quatslice3(2,0) != 1 || quatslice3(2,1) != 2 || quatslice3(2,2) != 3 || quatslice3(2,3) != 4 || -// quatslice3(3,0) != 1 || quatslice3(3,1) != 2 || quatslice3(3,2) != 3 || quatslice3(3,3) != 4 || -// quatslice3(4,0) != 1 || quatslice3(4,1) != 2 || quatslice3(4,2) != 3 || quatslice3(4,3) != 4 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice3 << "\n" -// << " Expected result:\n(( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 )\n( 1 2 3 4 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 1 || quat_(1,0,1) != 2 || quat_(1,0,2) != 3 || quat_(1,0,3) != 4 || -// quat_(1,1,0) != 1 || quat_(1,1,1) != 2 || quat_(1,1,2) != 3 || quat_(1,1,3) != 4 || -// quat_(1,2,0) != 1 || quat_(1,2,1) != 2 || quat_(1,2,2) != 3 || quat_(1,2,3) != 4 || -// quat_(1,3,0) != 1 || quat_(1,3,1) != 2 || quat_(1,3,2) != 3 || quat_(1,3,3) != 4 || -// quat_(1,4,0) != 1 || quat_(1,4,1) != 2 || quat_(1,4,2) != 3 || quat_(1,4,3) != 4 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 1 2 3 4 )\n" -// " ( 1 2 3 4 )\n" -// " ( 1 2 3 4 )\n" -// " ( 1 2 3 4 )\n" -// " ( 1 2 3 4 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "initializer list assignment (incomplete list)"; -// -// initialize(); -// -// RT quatslice3 = blaze::quatslice( quat_, 1UL ); -// quatslice3 = {{1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}}; -// -// checkRows ( quatslice3, 5UL ); -// checkColumns ( quatslice3, 4UL ); -// checkCapacity( quatslice3, 20UL ); -// checkNonZeros( quatslice3, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice3(0,0) != 1 || quatslice3(0,1) != 2 || quatslice3(0,2) != 0 || quatslice3(0,3) != 0 || -// quatslice3(1,0) != 1 || quatslice3(1,1) != 2 || quatslice3(1,2) != 0 || quatslice3(1,3) != 0 || -// quatslice3(2,0) != 1 || quatslice3(2,1) != 2 || quatslice3(2,2) != 0 || quatslice3(2,3) != 0 || -// quatslice3(3,0) != 1 || quatslice3(3,1) != 2 || quatslice3(3,2) != 0 || quatslice3(3,3) != 0 || -// quatslice3(4,0) != 1 || quatslice3(4,1) != 2 || quatslice3(4,2) != 0 || quatslice3(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice3 << "\n" -// << " Expected result:\n(( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 )\n( 1 2 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 1 || quat_(1,0,1) != 2 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 1 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 1 || quat_(1,2,1) != 2 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 1 || quat_(1,3,1) != 2 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 1 || quat_(1,4,1) != 2 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 1 2 0 0 )\n" -// " ( 1 2 0 0 )\n" -// " ( 1 2 0 0 )\n" -// " ( 1 2 0 0 )\n" -// " ( 1 2 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // copy assignment -// //===================================================================================== -// -// { -// test_ = "QuatSlice copy assignment"; -// -// initialize(); -// -// RT quatslice1 = blaze::quatslice( quat_, 0UL ); -// quatslice1 = 0; -// quatslice1 = blaze::quatslice( quat_, 1UL ); -// -// checkRows ( quatslice1, 5UL ); -// checkColumns ( quatslice1, 4UL ); -// checkCapacity( quatslice1, 20UL ); -// checkNonZeros( quatslice1, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 0 || quatslice1(0,2) != 0 || quatslice1(0,3) != 0 || -// quatslice1(1,0) != 0 || quatslice1(1,1) != 1 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || -// quatslice1(2,0) != -2 || quatslice1(2,1) != 0 || quatslice1(2,2) != -3 || quatslice1(2,3) != 0 || -// quatslice1(3,0) != 0 || quatslice1(3,1) != 4 || quatslice1(3,2) != 5 || quatslice1(3,3) != -6 || -// quatslice1(4,0) != 7 || quatslice1(4,1) != -8 || quatslice1(4,2) != 9 || quatslice1(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice1 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // dense quaternion assignment -// //===================================================================================== -// -// { -// test_ = "dense quaternion assignment (mixed type)"; -// -// initialize(); -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// -// blaze::DynamicMatrix m1; -// m1 = {{0, 8, 0, 9}, {0}, {0}, {0}, {0}}; -// -// quatslice1 = m1; -// -// checkRows ( quatslice1, 5UL ); -// checkColumns ( quatslice1, 4UL ); -// checkCapacity( quatslice1, 20UL ); -// checkNonZeros( quatslice1, 2UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 12UL ); -// -// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || -// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || -// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || -// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || -// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice1 << "\n" -// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 9 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion assignment (mixed type)"; -// -// initialize(); -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// -// blaze::DynamicMatrix m1; -// m1 = {{0, 8, 0, 9}, {0}, {0}, {0}, {0}}; -// -// quatslice1 = m1; -// -// checkRows ( quatslice1, 5UL ); -// checkColumns ( quatslice1, 4UL ); -// checkCapacity( quatslice1, 20UL ); -// checkNonZeros( quatslice1, 2UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 12UL ); -// -// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || -// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || -// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || -// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || -// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice1 << "\n" -// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 9 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion assignment (aligned/padded)"; -// -// using blaze::aligned; -// using blaze::padded; -// using blaze::rowMajor; -// -// initialize(); -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// -// using AlignedPadded = blaze::CustomMatrix; -// std::unique_ptr memory( blaze::allocate( 80UL ) ); -// AlignedPadded m1( memory.get(), 5UL, 4UL, 16UL ); -// m1 = 0; -// m1(0,0) = 0; -// m1(0,1) = 8; -// m1(0,2) = 0; -// m1(0,3) = 9; -// -// quatslice1 = m1; -// -// checkRows ( quatslice1, 5UL ); -// checkColumns ( quatslice1, 4UL ); -// checkCapacity( quatslice1, 20UL ); -// checkNonZeros( quatslice1, 2UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 12UL ); -// -// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || -// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || -// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || -// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || -// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice1 << "\n" -// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 9 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion assignment (unaligned/unpadded)"; -// -// using blaze::unaligned; -// using blaze::unpadded; -// using blaze::rowMajor; -// -// initialize(); -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// -// using UnalignedUnpadded = blaze::CustomMatrix; -// std::unique_ptr memory( new int[21] ); -// UnalignedUnpadded m1( memory.get()+1UL, 5UL, 4UL ); -// m1 = 0; -// m1(0,0) = 0; -// m1(0,1) = 8; -// m1(0,2) = 0; -// m1(0,3) = 9; -// -// quatslice1 = m1; -// -// checkRows ( quatslice1, 5UL ); -// checkColumns ( quatslice1, 4UL ); -// checkCapacity( quatslice1, 20UL ); -// checkNonZeros( quatslice1, 2UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 12UL ); -// -// if( quatslice1(0,0) != 0 || quatslice1(0,1) != 8 || quatslice1(0,2) != 0 || quatslice1(0,3) != 9 || -// quatslice1(1,0) != 0 || quatslice1(1,1) != 0 || quatslice1(1,2) != 0 || quatslice1(1,3) != 0 || -// quatslice1(2,0) != 0 || quatslice1(2,1) != 0 || quatslice1(2,2) != 0 || quatslice1(2,3) != 0 || -// quatslice1(3,0) != 0 || quatslice1(3,1) != 0 || quatslice1(3,2) != 0 || quatslice1(3,3) != 0 || -// quatslice1(4,0) != 0 || quatslice1(4,1) != 0 || quatslice1(4,2) != 0 || quatslice1(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice1 << "\n" -// << " Expected result:\n(( 0 8 0 9 )\n(0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 8 || quat_(1,0,2) != 0 || quat_(1,0,3) != 9 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 9 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice addition assignment operators. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the addition assignment operators of the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testAddAssign() -//{ -// //===================================================================================== -// // QuatSlice addition assignment -// //===================================================================================== -// -// { -// test_ = "QuatSlice addition assignment"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 += blaze::quatslice( quat_, 0UL ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || -// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || -// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 2 0 0 )\n" -// " ( -4 0 -6 0 )\n" -// " ( 0 8 10 -12 )\n" -// " ( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // dense quaternion addition assignment -// //===================================================================================== -// -// { -// test_ = "dense quaternion addition assignment (mixed type)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// const blaze::DynamicMatrix vec{{0, 0, 0, 0}, -// {0, 1, 0, 0}, -// {-2, 0, -3, 0}, -// {0, 4, 5, -6}, -// {7, -8, 9, 10}}; -// -// quatslice2 += vec; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || -// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || -// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 2 0 0 )\n" -// " ( -4 0 -6 0 )\n" -// " ( 0 8 10 -12 )\n" -// " ( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion addition assignment (aligned/padded)"; -// -// using blaze::aligned; -// using blaze::padded; -// using blaze::rowMajor; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// using AlignedPadded = blaze::CustomMatrix; -// std::unique_ptr memory( blaze::allocate( 80UL ) ); -// AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); -// m(0,0) = 0; -// m(0,1) = 0; -// m(0,2) = 0; -// m(0,3) = 0; -// m(1,0) = 0; -// m(1,1) = 1; -// m(1,2) = 0; -// m(1,3) = 0; -// m(2,0) = -2; -// m(2,1) = 0; -// m(2,2) = -3; -// m(2,3) = 0; -// m(3,0) = 0; -// m(3,1) = 4; -// m(3,2) = 5; -// m(3,3) = -6; -// m(4,0) = 7; -// m(4,1) = -8; -// m(4,2) = 9; -// m(4,3) = 10; -// -// quatslice2 += m; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || -// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || -// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 2 0 0 )\n" -// " ( -4 0 -6 0 )\n" -// " ( 0 8 10 -12 )\n" -// " ( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion addition assignment (unaligned/unpadded)"; -// -// using blaze::unaligned; -// using blaze::unpadded; -// using blaze::rowMajor; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// using UnalignedUnpadded = blaze::CustomMatrix; -// std::unique_ptr memory( new int[21] ); -// UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); -// m(0,0) = 0; -// m(0,1) = 0; -// m(0,2) = 0; -// m(0,3) = 0; -// m(1,0) = 0; -// m(1,1) = 1; -// m(1,2) = 0; -// m(1,3) = 0; -// m(2,0) = -2; -// m(2,1) = 0; -// m(2,2) = -3; -// m(2,3) = 0; -// m(3,0) = 0; -// m(3,1) = 4; -// m(3,2) = 5; -// m(3,3) = -6; -// m(4,0) = 7; -// m(4,1) = -8; -// m(4,2) = 9; -// m(4,3) = 10; -// -// quatslice2 += m; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 2 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -4 || quatslice2(2,1) != 0 || quatslice2(2,2) != -6 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 8 || quatslice2(3,2) != 10 || quatslice2(3,3) != -12 || -// quatslice2(4,0) != 14 || quatslice2(4,1) != -16 || quatslice2(4,2) != 18 || quatslice2(4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 2 0 0 )\n( -4 0 -6 0 )\n( 0 8 10 -12 )\n( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 2 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -4 || quat_(1,2,1) != 0 || quat_(1,2,2) != -6 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 8 || quat_(1,3,2) != 10 || quat_(1,3,3) != -12 || -// quat_(1,4,0) != 14 || quat_(1,4,1) != -16 || quat_(1,4,2) != 18 || quat_(1,4,3) != 20 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 2 0 0 )\n" -// " ( -4 0 -6 0 )\n" -// " ( 0 8 10 -12 )\n" -// " ( 14 -16 18 20 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice subtraction assignment operators. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the subtraction assignment operators of the QuatSlice -//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testSubAssign() -//{ -// //===================================================================================== -// // QuatSlice subtraction assignment -// //===================================================================================== -// -// { -// test_ = "QuatSlice subtraction assignment"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 -= blaze::quatslice( quat_, 0UL ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 0UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || -// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // dense quaternion subtraction assignment -// //===================================================================================== -// -// { -// test_ = "dense quaternion subtraction assignment (mixed type)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// const blaze::DynamicMatrix vec{{0, 0, 0, 0}, -// {0, 1, 0, 0}, -// {-2, 0, -3, 0}, -// {0, 4, 5, -6}, -// {7, -8, 9, 10}}; -// -// quatslice2 -= vec; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 0UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || -// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// } -// } -// -// { -// test_ = "dense quaternion subtraction assignment (aligned/padded)"; -// -// using blaze::aligned; -// using blaze::padded; -// using blaze::rowMajor; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// using AlignedPadded = blaze::CustomMatrix; -// std::unique_ptr memory( blaze::allocate( 80UL ) ); -// AlignedPadded m( memory.get(), 5UL, 4UL, 16UL ); -// m(0,0) = 0; -// m(0,1) = 0; -// m(0,2) = 0; -// m(0,3) = 0; -// m(1,0) = 0; -// m(1,1) = 1; -// m(1,2) = 0; -// m(1,3) = 0; -// m(2,0) = -2; -// m(2,1) = 0; -// m(2,2) = -3; -// m(2,3) = 0; -// m(3,0) = 0; -// m(3,1) = 4; -// m(3,2) = 5; -// m(3,3) = -6; -// m(4,0) = 7; -// m(4,1) = -8; -// m(4,2) = 9; -// m(4,3) = 10; -// -// quatslice2 -= m; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 0UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || -// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion subtraction assignment (unaligned/unpadded)"; -// -// using blaze::unaligned; -// using blaze::unpadded; -// using blaze::rowMajor; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// using UnalignedUnpadded = blaze::CustomMatrix; -// std::unique_ptr memory( new int[21] ); -// UnalignedUnpadded m( memory.get()+1UL, 5UL, 4UL ); -// m(0,0) = 0; -// m(0,1) = 0; -// m(0,2) = 0; -// m(0,3) = 0; -// m(1,0) = 0; -// m(1,1) = 1; -// m(1,2) = 0; -// m(1,3) = 0; -// m(2,0) = -2; -// m(2,1) = 0; -// m(2,2) = -3; -// m(2,3) = 0; -// m(3,0) = 0; -// m(3,1) = 4; -// m(3,2) = 5; -// m(3,3) = -6; -// m(4,0) = 7; -// m(4,1) = -8; -// m(4,2) = 9; -// m(4,3) = 10; -// -// quatslice2 -= m; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 0UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || -// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice multiplication assignment operators. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the multiplication assignment operators of the QuatSlice -//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testMultAssign() -//{ -// //===================================================================================== -// // QuatSlice multiplication assignment -// //===================================================================================== -// -// { -// test_ = "QuatSlice multiplication assignment"; -// -// initialize(); -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// quatslice2 *= blaze::quatslice( m, 0UL ); -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || -// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || -// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || -// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || -// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 90 114 138 )\n" -// " ( 54 69 84 )\n" -// " ( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // dense quaternion multiplication assignment -// //===================================================================================== -// -// { -// test_ = "dense quaternion multiplication assignment (mixed type)"; -// -// initialize(); -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// -// const blaze::DynamicMatrix m1{ -// {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; -// -// quatslice2 *= m1; -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || -// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || -// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || -// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || -// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 90 114 138 )\n" -// " ( 54 69 84 )\n" -// " ( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion multiplication assignment (aligned/padded)"; -// -// using blaze::aligned; -// using blaze::padded; -// using blaze::rowMajor; -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// -// -// using AlignedPadded = blaze::CustomMatrix; -// std::unique_ptr memory( blaze::allocate( 48UL ) ); -// AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); -// m1(0,0) = 1; -// m1(0,1) = 2; -// m1(0,2) = 3; -// m1(1,0) = 4; -// m1(1,1) = 5; -// m1(1,2) = 6; -// m1(2,0) = 7; -// m1(2,1) = 8; -// m1(2,2) = 9; -// -// quatslice2 *= m1; -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || -// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || -// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || -// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || -// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 90 114 138 )\n" -// " ( 54 69 84 )\n" -// " ( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion multiplication assignment (unaligned/unpadded)"; -// -// using blaze::unaligned; -// using blaze::unpadded; -// using blaze::rowMajor; -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// -// using UnalignedUnpadded = blaze::CustomMatrix; -// std::unique_ptr memory( new int[10] ); -// UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); -// m1(0,0) = 1; -// m1(0,1) = 2; -// m1(0,2) = 3; -// m1(1,0) = 4; -// m1(1,1) = 5; -// m1(1,2) = 6; -// m1(2,0) = 7; -// m1(2,1) = 8; -// m1(2,2) = 9; -// -// quatslice2 *= m1; -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 90 || quatslice2(0,1) != 114 || quatslice2(0,2) != 138 || -// quatslice2(1,0) != 54 || quatslice2(1,1) != 69 || quatslice2(1,2) != 84 || -// quatslice2(2,0) != 18 || quatslice2(2,1) != 24 || quatslice2(2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 90 114 138 )\n( 54 69 84 )\n( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 90 || m(1,0,1) != 114 || m(1,0,2) != 138 || -// m(1,1,0) != 54 || m(1,1,1) != 69 || m(1,1,2) != 84 || -// m(1,2,0) != 18 || m(1,2,1) != 24 || m(1,2,2) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 90 114 138 )\n" -// " ( 54 69 84 )\n" -// " ( 18 24 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice Schur product assignment operators. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the Schur product assignment operators of the QuatSlice -//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testSchurAssign() -//{ -// //===================================================================================== -// // QuatSlice Schur product assignment -// //===================================================================================== -// -// { -// test_ = "QuatSlice Schur product assignment"; -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// quatslice2 %= blaze::quatslice( m, 0UL ); -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || -// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || -// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || -// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || -// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 9 16 21 )\n" -// " ( 24 25 24 )\n" -// " ( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // dense quaternion Schur product assignment -// //===================================================================================== -// -// { -// test_ = "dense vector Schur product assignment (mixed type)"; -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// -// const blaze::DynamicMatrix m1{ -// {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; -// -// quatslice2 %= m1; -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || -// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || -// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || -// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || -// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 9 16 21 )\n" -// " ( 24 25 24 )\n" -// " ( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion Schur product assignment (aligned/padded)"; -// -// using blaze::aligned; -// using blaze::padded; -// using blaze::rowMajor; -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// -// using AlignedPadded = blaze::CustomMatrix; -// std::unique_ptr memory( blaze::allocate( 48UL ) ); -// AlignedPadded m1( memory.get(), 3UL, 3UL, 16UL ); -// m1(0,0) = 1; -// m1(0,1) = 2; -// m1(0,2) = 3; -// m1(1,0) = 4; -// m1(1,1) = 5; -// m1(1,2) = 6; -// m1(2,0) = 7; -// m1(2,1) = 8; -// m1(2,2) = 9; -// -// quatslice2 %= m1; -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || -// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || -// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || -// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || -// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 9 16 21 )\n" -// " ( 24 25 24 )\n" -// " ( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// { -// test_ = "dense quaternion Schur product assignment (unaligned/unpadded)"; -// -// using blaze::unaligned; -// using blaze::unpadded; -// using blaze::rowMajor; -// -// blaze::DynamicTensor m{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, -// {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; -// -// RT quatslice2 = blaze::quatslice( m, 1UL ); -// -// using UnalignedUnpadded = blaze::CustomMatrix; -// std::unique_ptr memory( new int[10] ); -// UnalignedUnpadded m1( memory.get()+1UL, 3UL , 3UL); -// m1(0,0) = 1; -// m1(0,1) = 2; -// m1(0,2) = 3; -// m1(1,0) = 4; -// m1(1,1) = 5; -// m1(1,2) = 6; -// m1(2,0) = 7; -// m1(2,1) = 8; -// m1(2,2) = 9; -// -// quatslice2 %= m1; -// -// checkRows ( quatslice2, 3UL ); -// checkColumns ( quatslice2, 3UL ); -// checkCapacity( quatslice2, 9UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( m, 3UL ); -// checkColumns ( m, 3UL ); -// checkQuats ( m, 2UL ); -// checkNonZeros( m, 18UL ); -// -// if( quatslice2(0,0) != 9 || quatslice2(0,1) != 16 || quatslice2(0,2) != 21 || -// quatslice2(1,0) != 24 || quatslice2(1,1) != 25 || quatslice2(1,2) != 24 || -// quatslice2(2,0) != 21 || quatslice2(2,1) != 16 || quatslice2(2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( m(0,0,0) != 1 || m(0,0,1) != 2 || m(0,0,2) != 3 || -// m(0,1,0) != 4 || m(0,1,1) != 5 || m(0,1,2) != 6 || -// m(0,2,0) != 7 || m(0,2,1) != 8 || m(0,2,2) != 9 || -// m(1,0,0) != 9 || m(1,0,1) != 16 || m(1,0,2) != 21 || -// m(1,1,0) != 24 || m(1,1,1) != 25 || m(1,1,2) != 24 || -// m(1,2,0) != 21 || m(1,2,1) != 16 || m(1,2,2) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 1 2 3 )\n" -// " ( 4 5 6 )\n" -// " ( 7 8 9 ))\n" -// "(( 9 16 21 )\n" -// " ( 24 25 24 )\n" -// " ( 21 16 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of all QuatSlice (self-)scaling operations. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of all available ways to scale an instance of the QuatSlice -//// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testScaling() -//{ -// //===================================================================================== -// // self-scaling (v*=2) -// //===================================================================================== -// -// { -// test_ = "self-scaling (v*=2)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 *= 3; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || -// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || -// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 3 0 0 )\n" -// " ( -6 0 -9 0 )\n" -// " ( 0 12 15 -18 )\n" -// " ( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // self-scaling (v=v*2) -// //===================================================================================== -// -// { -// test_ = "self-scaling (v=v*3)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 = quatslice2 * 3; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || -// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || -// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 3 0 0 )\n" -// " ( -6 0 -9 0 )\n" -// " ( 0 12 15 -18 )\n" -// " ( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // self-scaling (v=3*v) -// //===================================================================================== -// -// { -// test_ = "self-scaling (v=3*v)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 = 3 * quatslice2; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || -// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || -// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 3 0 0 )\n" -// " ( -6 0 -9 0 )\n" -// " ( 0 12 15 -18 )\n" -// " ( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // self-scaling (v/=s) -// //===================================================================================== -// -// { -// test_ = "self-scaling (v/=s)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 /= (1.0/3.0); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || -// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || -// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 3 0 0 )\n" -// " ( -6 0 -9 0 )\n" -// " ( 0 12 15 -18 )\n" -// " ( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // self-scaling (v=v/s) -// //===================================================================================== -// -// { -// test_ = "self-scaling (v=v/s)"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2 = quatslice2 / (1.0/3.0); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || -// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || -// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 3 0 0 )\n" -// " ( -6 0 -9 0 )\n" -// " ( 0 12 15 -18 )\n" -// " ( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// -// //===================================================================================== -// // QuatSlice::scale() -// //===================================================================================== -// -// { -// test_ = "QuatSlice::scale()"; -// -// initialize(); -// -// // Integral scaling the 3rd quatslice -// { -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2.scale( 3 ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 3 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -6 || quatslice2(2,1) != 0 || quatslice2(2,2) != -9 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 12 || quatslice2(3,2) != 15 || quatslice2(3,3) != -18 || -// quatslice2(4,0) != 21 || quatslice2(4,1) != -24 || quatslice2(4,2) != 27 || quatslice2(4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 3 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -6 || quat_(1,2,1) != 0 || quat_(1,2,2) != -9 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 12 || quat_(1,3,2) != 15 || quat_(1,3,3) != -18 || -// quat_(1,4,0) != 21 || quat_(1,4,1) != -24 || quat_(1,4,2) != 27 || quat_(1,4,3) != 30 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 3 0 0 )\n" -// " ( -6 0 -9 0 )\n" -// " ( 0 12 15 -18 )\n" -// " ( 21 -24 27 30 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// initialize(); -// -// // Floating point scaling the 3rd quatslice -// { -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// quatslice2.scale( 0.5 ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 19UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -1 || quatslice2(2,1) != 0 || quatslice2(2,2) != -1 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 2 || quatslice2(3,2) != 2 || quatslice2(3,3) != -3 || -// quatslice2(4,0) != 3 || quatslice2(4,1) != -4 || quatslice2(4,2) != 4 || quatslice2(4,3) != 5 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( -1 0 -1 0 )\n( 0 12 2 -3 )\n( 3 -4 4 5 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -1 || quat_(1,2,1) != 0 || quat_(1,2,2) != -1 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 2 || quat_(1,3,2) != 2 || quat_(1,3,3) != -3 || -// quat_(1,4,0) != 3 || quat_(1,4,1) != -4 || quat_(1,4,2) != 4 || quat_(1,4,3) != 5 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed self-scaling operation\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( -1 0 -1 0 )\n" -// " ( 0 2 2 -3 )\n" -// " ( 3 -4 4 5 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice function call operator. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of adding and accessing elements via the function call operator -//// of the QuatSlice specialization. In case an error is detected, a \a std::runtime_error exception -//// is thrown. -//*/ -//void DenseGeneralTest::testFunctionCall() -//{ -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "QuatSlice::operator()"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// // Assignment to the element at index (0,1) -// quatslice2(0,1) = 9; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 11UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 21UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 9 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Assignment to the element at index (2,2) -// quatslice2(2,2) = 0; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 9 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Assignment to the element at index (4,1) -// quatslice2(4,1) = -9; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 9 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Addition assignment to the element at index (0,1) -// quatslice2(0,1) += -3; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Subtraction assignment to the element at index (2,0) -// quatslice2(2,0) -= 6; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -8 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -8 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Multiplication assignment to the element at index (4,0) -// quatslice2(4,0) *= -3; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -8 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != -21 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -8 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Division assignment to the element at index (3,3) -// quatslice2(3,3) /= 2; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 6 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -8 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -3 || -// quatslice2(4,0) != -21 || quatslice2(4,1) != -9 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -3 || -// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -8 0 0 0 )\n" -// " ( 0 4 5 -3 )\n" -// " ( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice at() operator. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of adding and accessing elements via the at() operator -//// of the QuatSlice specialization. In case an error is detected, a \a std::runtime_error exception -//// is thrown. -//*/ -//void DenseGeneralTest::testAt() -//{ -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "QuatSlice::at()"; -// -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// // Assignment to the element at index (0,1) -// quatslice2.at(0,1) = 9; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 11UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 21UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 9 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != -3 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || -// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -8 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Assignment to the element at index (2,2) -// quatslice2.at(2,2) = 0; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 9 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || -// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -8 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -8 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Assignment to the element at index (4,1) -// quatslice2.at(4,1) = -9; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 9 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || -// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 9 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 9 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Addition assignment to the element at index (0,1) -// quatslice2.at(0,1) += -3; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -2 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || -// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Subtraction assignment to the element at index (2,0) -// quatslice2.at(2,0) -= 6; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -8 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || -// quatslice2.at(4,0) != 7 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 7 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -8 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Multiplication assignment to the element at index (4,0) -// quatslice2.at(4,0) *= -3; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -8 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -6 || -// quatslice2.at(4,0) != -21 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -6 )\n( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -8 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Division assignment to the element at index (3,3) -// quatslice2.at(3,3) /= 2; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2.at(0,0) != 0 || quatslice2.at(0,1) != 6 || quatslice2.at(0,2) != 0 || quatslice2.at(0,3) != 0 || -// quatslice2.at(1,0) != 0 || quatslice2.at(1,1) != 1 || quatslice2.at(1,2) != 0 || quatslice2.at(1,3) != 0 || -// quatslice2.at(2,0) != -8 || quatslice2.at(2,1) != 0 || quatslice2.at(2,2) != 0 || quatslice2.at(2,3) != 0 || -// quatslice2.at(3,0) != 0 || quatslice2.at(3,1) != 4 || quatslice2.at(3,2) != 5 || quatslice2.at(3,3) != -3 || -// quatslice2.at(4,0) != -21 || quatslice2.at(4,1) != -9 || quatslice2.at(4,2) != 9 || quatslice2.at(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 6 0 0 )\n( 0 1 0 0 )\n( -8 0 0 0 )\n( 0 4 5 -3 )\n( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 6 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -8 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -3 || -// quat_(1,4,0) != -21 || quat_(1,4,1) != -9 || quat_(1,4,2) != 9 || quat_(1,4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: At() failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 6 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -8 0 0 0 )\n" -// " ( 0 4 5 -3 )\n" -// " ( -21 -9 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the QuatSlice iterator implementation. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the iterator implementation of the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testIterator() -//{ -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// initialize(); -// -// // Testing the Iterator default constructor -// { -// test_ = "Iterator default constructor"; -// -// RT::Iterator it{}; -// -// if( it != RT::Iterator() ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed iterator default constructor\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Testing the ConstIterator default constructor -// { -// test_ = "ConstIterator default constructor"; -// -// RT::ConstIterator it{}; -// -// if( it != RT::ConstIterator() ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed iterator default constructor\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Testing conversion from Iterator to ConstIterator -// { -// test_ = "Iterator/ConstIterator conversion"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// RT::ConstIterator it( begin( quatslice2, 2UL ) ); -// -// if( it == end( quatslice2, 2UL ) || *it != -2 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Failed iterator conversion detected\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Counting the number of elements in 1st quatslice via Iterator (end-begin) -// { -// test_ = "Iterator subtraction (end-begin)"; -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// const ptrdiff_t number( end( quatslice1, 2UL ) - begin( quatslice1, 2UL ) ); -// -// if( number != 4L ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid number of elements detected\n" -// << " Details:\n" -// << " Number of elements : " << number << "\n" -// << " Expected number of elements: 4\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Counting the number of elements in 1st quatslice via Iterator (begin-end) -// { -// test_ = "Iterator subtraction (begin-end)"; -// -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// const ptrdiff_t number( begin( quatslice1, 2UL ) - end( quatslice1, 2UL ) ); -// -// if( number != -4L ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid number of elements detected\n" -// << " Details:\n" -// << " Number of elements : " << number << "\n" -// << " Expected number of elements: -4\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Counting the number of elements in 2nd quatslice via ConstIterator (end-begin) -// { -// test_ = "ConstIterator subtraction (end-begin)"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// const ptrdiff_t number( cend( quatslice2, 2UL ) - cbegin( quatslice2, 2UL ) ); -// -// if( number != 4L ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid number of elements detected\n" -// << " Details:\n" -// << " Number of elements : " << number << "\n" -// << " Expected number of elements: 4\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Counting the number of elements in 2nd quatslice via ConstIterator (begin-end) -// { -// test_ = "ConstIterator subtraction (begin-end)"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// const ptrdiff_t number( cbegin( quatslice2, 2UL ) - cend( quatslice2, 2UL ) ); -// -// if( number != -4L ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid number of elements detected\n" -// << " Details:\n" -// << " Number of elements : " << number << "\n" -// << " Expected number of elements: -4\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Testing read-only access via ConstIterator -// { -// test_ = "read-only access via ConstIterator"; -// -// RT quatslice3 = blaze::quatslice( quat_, 0UL ); -// RT::ConstIterator it ( cbegin( quatslice3, 4UL ) ); -// RT::ConstIterator end( cend( quatslice3, 4UL ) ); -// -// if( it == end || *it != 7 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid initial iterator detected\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// ++it; -// -// if( it == end || *it != -8 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator pre-increment failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// --it; -// -// if( it == end || *it != 7 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator pre-decrement failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// it++; -// -// if( it == end || *it != -8 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator post-increment failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// it--; -// -// if( it == end || *it != 7 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator post-decrement failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// it += 2UL; -// -// if( it == end || *it != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator addition assignment failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// it -= 2UL; -// -// if( it == end || *it != 7 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator subtraction assignment failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// it = it + 3UL; -// -// if( it == end || *it != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator/scalar addition failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// it = it - 3UL; +// This function performs a test of the Schur product assignment operators of the QuatSlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testSchurAssign() +{ + //===================================================================================== + // QuatSlice Schur product assignment + //===================================================================================== + + { + test_ = "QuatSlice Schur product assignment"; + + blaze::DynamicArray< 4, int > a{ {{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}, + {{{-1, -2, -3}, {-4, -5, -6}, {-7, -8, -9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}} }; + + RT quatslice2 = blaze::quatslice( a, 1UL ); + quatslice2 %= blaze::quatslice( a, 0UL ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 3UL ); + checkColumns ( quatslice2, 3UL ); + checkCapacity( quatslice2, 18UL ); + checkNonZeros( quatslice2, 18UL ); + checkQuats ( a, 2UL ); + checkRows ( a, 3UL ); + checkColumns ( a, 3UL ); + checkPages ( a, 2UL ); + checkNonZeros( a, 36UL ); + + if( quatslice2(0,0,0) != -1 || quatslice2(0,0,1) != -4 || quatslice2(0,0,2) != -9 || + quatslice2(0,1,0) != -16 || quatslice2(0,1,1) != -25 || quatslice2(0,1,2) != -36 || + quatslice2(0,2,0) != -49 || quatslice2(0,2,1) != -64 || quatslice2(0,2,2) != -81 || + quatslice2(1,0,0) != 81 || quatslice2(1,0,1) != 64 || quatslice2(1,0,2) != 49 || + quatslice2(1,1,0) != 36 || quatslice2(1,1,1) != 25 || quatslice2(1,1,2) != 16 || + quatslice2(1,2,0) != 9 || quatslice2(1,2,1) != 4 || quatslice2(1,2,2) != 1) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( a(1,0,0,0) != -1 || a(1,0,0,1) != -4 || a(1,0,0,2) != -9 || + a(1,0,1,0) != -16 || a(1,0,1,1) != -25 || a(1,0,1,2) != -36 || + a(1,0,2,0) != -49 || a(1,0,2,1) != -64 || a(1,0,2,2) != -81 || + a(1,1,0,0) != 81 || a(1,1,0,1) != 64 || a(1,1,0,2) != 49 || + a(1,1,1,0) != 36 || a(1,1,1,1) != 25 || a(1,1,1,2) != 16 || + a(1,1,2,0) != 9 || a(1,1,2,1) != 4 || a(1,1,2,2) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur assignment failed\n" + << " Details:\n" + << " Result:\n" << a << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // dense quaternion Schur product assignment + //===================================================================================== + + { + test_ = "dense vector Schur product assignment (mixed type)"; + + blaze::DynamicArray< 4, int > a{{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}, + {{{-1, -2, -3}, {-4, -5, -6}, {-7, -8, -9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}}; + + RT quatslice2 = blaze::quatslice( a, 1UL ); + + const blaze::DynamicTensor< short > a1{ + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}; + + quatslice2 %= a1; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 3UL ); + checkColumns ( quatslice2, 3UL ); + checkCapacity( quatslice2, 18UL ); + checkNonZeros( quatslice2, 18UL ); + checkQuats ( a, 2UL ); + checkRows ( a, 3UL ); + checkColumns ( a, 3UL ); + checkPages ( a, 2UL ); + checkNonZeros( a, 36UL ); + + if( quatslice2(0,0,0) != -1 || quatslice2(0,0,1) != -4 || quatslice2(0,0,2) != -9 || + quatslice2(0,1,0) != -16 || quatslice2(0,1,1) != -25 || quatslice2(0,1,2) != -36 || + quatslice2(0,2,0) != -49 || quatslice2(0,2,1) != -64 || quatslice2(0,2,2) != -81 || + quatslice2(1,0,0) != 81 || quatslice2(1,0,1) != 64 || quatslice2(1,0,2) != 49 || + quatslice2(1,1,0) != 36 || quatslice2(1,1,1) != 25 || quatslice2(1,1,2) != 16 || + quatslice2(1,2,0) != 9 || quatslice2(1,2,1) != 4 || quatslice2(1,2,2) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( a(1,0,0,0) != -1 || a(1,0,0,1) != -4 || a(1,0,0,2) != -9 || + a(1,0,1,0) != -16 || a(1,0,1,1) != -25 || a(1,0,1,2) != -36 || + a(1,0,2,0) != -49 || a(1,0,2,1) != -64 || a(1,0,2,2) != -81 || + a(1,1,0,0) != 81 || a(1,1,0,1) != 64 || a(1,1,0,2) != 49 || + a(1,1,1,0) != 36 || a(1,1,1,1) != 25 || a(1,1,1,2) != 16 || + a(1,1,2,0) != 9 || a(1,1,2,1) != 4 || a(1,1,2,2) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur assignment failed\n" + << " Details:\n" + << " Result:\n" << a << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense quaternion Schur product assignment (aligned/padded)"; + + using blaze::aligned; + using blaze::padded; + + blaze::DynamicArray< 4, int > a{{{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}, + {{{-1, -2, -3}, {-4, -5, -6}, {-7, -8, -9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}}}; + + RT quatslice2 = blaze::quatslice( a, 1UL ); + + using AlignedPadded = blaze::CustomTensor; + std::unique_ptr memory( blaze::allocate( 96UL ) ); + AlignedPadded a1( memory.get(), 2UL, 3UL, 3UL, 16UL ); + a1(0,0,0) = 1; + a1(0,0,1) = 2; + a1(0,0,2) = 3; + a1(0,1,0) = 4; + a1(0,1,1) = 5; + a1(0,1,2) = 6; + a1(0,2,0) = 7; + a1(0,2,1) = 8; + a1(0,2,2) = 9; + a1(1,0,0) = 9; + a1(1,0,1) = 8; + a1(1,0,2) = 7; + a1(1,1,0) = 6; + a1(1,1,1) = 5; + a1(1,1,2) = 4; + a1(1,2,0) = 3; + a1(1,2,1) = 2; + a1(1,2,2) = 1; + + quatslice2 %= a1; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 3UL ); + checkColumns ( quatslice2, 3UL ); + checkCapacity( quatslice2, 18UL ); + checkNonZeros( quatslice2, 18UL ); + checkQuats ( a, 2UL ); + checkRows ( a, 3UL ); + checkColumns ( a, 3UL ); + checkPages ( a, 2UL ); + checkNonZeros( a, 36UL ); + + if( quatslice2(0,0,0) != -1 || quatslice2(0,0,1) != -4 || quatslice2(0,0,2) != -9 || + quatslice2(0,1,0) != -16 || quatslice2(0,1,1) != -25 || quatslice2(0,1,2) != -36 || + quatslice2(0,2,0) != -49 || quatslice2(0,2,1) != -64 || quatslice2(0,2,2) != -81 || + quatslice2(1,0,0) != 81 || quatslice2(1,0,1) != 64 || quatslice2(1,0,2) != 49 || + quatslice2(1,1,0) != 36 || quatslice2(1,1,1) != 25 || quatslice2(1,1,2) != 16 || + quatslice2(1,2,0) != 9 || quatslice2(1,2,1) != 4 || quatslice2(1,2,2) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + + if( a(1,0,0,0) != -1 || a(1,0,0,1) != -4 || a(1,0,0,2) != -9 || + a(1,0,1,0) != -16 || a(1,0,1,1) != -25 || a(1,0,1,2) != -36 || + a(1,0,2,0) != -49 || a(1,0,2,1) != -64 || a(1,0,2,2) != -81 || + a(1,1,0,0) != 81 || a(1,1,0,1) != 64 || a(1,1,0,2) != 49 || + a(1,1,1,0) != 36 || a(1,1,1,1) != 25 || a(1,1,1,2) != 16 || + a(1,1,2,0) != 9 || a(1,1,2,1) != 4 || a(1,1,2,2) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur assignment failed\n" + << " Details:\n" + << " Result:\n" << a << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + { + test_ = "dense quaternion Schur product assignment (unaligned/unpadded)"; + + using blaze::unaligned; + using blaze::unpadded; + + blaze::DynamicArray< 4, int > a{ {{{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}, + {{{-1, -2, -3}, {-4, -5, -6}, {-7, -8, -9}}, + {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}} }; + + RT quatslice2 = blaze::quatslice(a, 1UL); + + using UnalignedUnpadded = blaze::CustomTensor; + std::unique_ptr memory(new int[20]); + UnalignedUnpadded a1(memory.get() + 1UL, 2UL, 3UL, 3UL); + a1(0, 0, 0) = 1; + a1(0, 0, 1) = 2; + a1(0, 0, 2) = 3; + a1(0, 1, 0) = 4; + a1(0, 1, 1) = 5; + a1(0, 1, 2) = 6; + a1(0, 2, 0) = 7; + a1(0, 2, 1) = 8; + a1(0, 2, 2) = 9; + a1(1, 0, 0) = 9; + a1(1, 0, 1) = 8; + a1(1, 0, 2) = 7; + a1(1, 1, 0) = 6; + a1(1, 1, 1) = 5; + a1(1, 1, 2) = 4; + a1(1, 2, 0) = 3; + a1(1, 2, 1) = 2; + a1(1, 2, 2) = 1; + + quatslice2 %= a1; + + checkPages(quatslice2, 2UL); + checkRows(quatslice2, 3UL); + checkColumns(quatslice2, 3UL); + checkCapacity(quatslice2, 18UL); + checkNonZeros(quatslice2, 18UL); + checkQuats(a, 2UL); + checkRows(a, 3UL); + checkColumns(a, 3UL); + checkPages(a, 2UL); + checkNonZeros(a, 36UL); + + if (quatslice2(0, 0, 0) != -1 || quatslice2(0, 0, 1) != -4 || quatslice2(0, 0, 2) != -9 || + quatslice2(0, 1, 0) != -16 || quatslice2(0, 1, 1) != -25 || quatslice2(0, 1, 2) != -36 || + quatslice2(0, 2, 0) != -49 || quatslice2(0, 2, 1) != -64 || quatslice2(0, 2, 2) != -81 || + quatslice2(1, 0, 0) != 81 || quatslice2(1, 0, 1) != 64 || quatslice2(1, 0, 2) != 49 || + quatslice2(1, 1, 0) != 36 || quatslice2(1, 1, 1) != 25 || quatslice2(1, 1, 2) != 16 || + quatslice2(1, 2, 0) != 9 || quatslice2(1, 2, 1) != 4 || quatslice2(1, 2, 2) != 1) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 9 16 21 )\n( 24 25 24 )\n( 21 16 9 ))\n"; + throw std::runtime_error(oss.str()); + } + + if (a(1, 0, 0, 0) != -1 || a(1, 0, 0, 1) != -4 || a(1, 0, 0, 2) != -9 || + a(1, 0, 1, 0) != -16 || a(1, 0, 1, 1) != -25 || a(1, 0, 1, 2) != -36 || + a(1, 0, 2, 0) != -49 || a(1, 0, 2, 1) != -64 || a(1, 0, 2, 2) != -81 || + a(1, 1, 0, 0) != 81 || a(1, 1, 0, 1) != 64 || a(1, 1, 0, 2) != 49 || + a(1, 1, 1, 0) != 36 || a(1, 1, 1, 1) != 25 || a(1, 1, 1, 2) != 16 || + a(1, 1, 2, 0) != 9 || a(1, 1, 2, 1) != 4 || a(1, 1, 2, 2) != 1) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Schur assignment failed\n" + << " Details:\n" + << " Result:\n" << a << "\n" + << " Expected result:\n(( 1 2 3 )\n" + " ( 4 5 6 )\n" + " ( 7 8 9 ))\n" + "(( 9 16 21 )\n" + " ( 24 25 24 )\n" + " ( 21 16 9 ))\n"; + throw std::runtime_error(oss.str()); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of all QuatSlice (self-)scaling operations. // -// if( it == end || *it != 7 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator/scalar subtraction failed\n"; -// throw std::runtime_error( oss.str() ); -// } +// \return void +// \exception std::runtime_error Error detected. // -// it = 4UL + it; +// This function performs a test of all available ways to scale an instance of the QuatSlice +// specialization. In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testScaling() +{ + //===================================================================================== + // self-scaling (v*=3) + //===================================================================================== + + { + test_ = "self-scaling (v*=3)"; + + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2 *= 3; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 3 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 36 || quatslice2(0,2,2) != -9 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 12 || quatslice2(0,3,2) != 15 || quatslice2(0,3,3) != -18 || + quatslice2(0,4,0) != 21 || quatslice2(0,4,1) != 84 || quatslice2(0,4,2) != 27 || quatslice2(0,4,3) != 30 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 3 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -6 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -9 || quatslice2(1,3,1) != 12 || quatslice2(1,3,2) != 15 || quatslice2(1,3,3) != 99 || + quatslice2(1,4,0) != 21 || quatslice2(1,4,1) != -24 || quatslice2(1,4,2) != 27 || quatslice2(1,4,3) != 33) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v=v*2) + //===================================================================================== + + { + test_ = "self-scaling (v=v*3)"; + + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2 = quatslice2 * 3; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 3 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 36 || quatslice2(0,2,2) != -9 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 12 || quatslice2(0,3,2) != 15 || quatslice2(0,3,3) != -18 || + quatslice2(0,4,0) != 21 || quatslice2(0,4,1) != 84 || quatslice2(0,4,2) != 27 || quatslice2(0,4,3) != 30 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 3 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -6 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -9 || quatslice2(1,3,1) != 12 || quatslice2(1,3,2) != 15 || quatslice2(1,3,3) != 99 || + quatslice2(1,4,0) != 21 || quatslice2(1,4,1) != -24 || quatslice2(1,4,2) != 27 || quatslice2(1,4,3) != 33) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v=3*v) + //===================================================================================== + + { + test_ = "self-scaling (v=3*v)"; + + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2 = 3 * quatslice2; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 3 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 36 || quatslice2(0,2,2) != -9 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 12 || quatslice2(0,3,2) != 15 || quatslice2(0,3,3) != -18 || + quatslice2(0,4,0) != 21 || quatslice2(0,4,1) != 84 || quatslice2(0,4,2) != 27 || quatslice2(0,4,3) != 30 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 3 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -6 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -9 || quatslice2(1,3,1) != 12 || quatslice2(1,3,2) != 15 || quatslice2(1,3,3) != 99 || + quatslice2(1,4,0) != 21 || quatslice2(1,4,1) != -24 || quatslice2(1,4,2) != 27 || quatslice2(1,4,3) != 33) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v/=s) + //===================================================================================== + + { + test_ = "self-scaling (v/=s)"; + + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2 /= (1.0/3.0); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 3 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 36 || quatslice2(0,2,2) != -9 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 12 || quatslice2(0,3,2) != 15 || quatslice2(0,3,3) != -18 || + quatslice2(0,4,0) != 21 || quatslice2(0,4,1) != 84 || quatslice2(0,4,2) != 27 || quatslice2(0,4,3) != 30 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 3 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -6 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -9 || quatslice2(1,3,1) != 12 || quatslice2(1,3,2) != 15 || quatslice2(1,3,3) != 99 || + quatslice2(1,4,0) != 21 || quatslice2(1,4,1) != -24 || quatslice2(1,4,2) != 27 || quatslice2(1,4,3) != 33) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // self-scaling (v=v/s) + //===================================================================================== + + { + test_ = "self-scaling (v=v/s)"; + + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2 = quatslice2 / (1.0/3.0); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 3 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 36 || quatslice2(0,2,2) != -9 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 12 || quatslice2(0,3,2) != 15 || quatslice2(0,3,3) != -18 || + quatslice2(0,4,0) != 21 || quatslice2(0,4,1) != 84 || quatslice2(0,4,2) != 27 || quatslice2(0,4,3) != 30 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 3 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -6 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -9 || quatslice2(1,3,1) != 12 || quatslice2(1,3,2) != 15 || quatslice2(1,3,3) != 99 || + quatslice2(1,4,0) != 21 || quatslice2(1,4,1) != -24 || quatslice2(1,4,2) != 27 || quatslice2(1,4,3) != 33) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + + //===================================================================================== + // QuatSlice::scale() + //===================================================================================== + + { + test_ = "QuatSlice::scale()"; + + initialize(); + + // Integral scaling the 2nd quatslice + { + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2.scale( 3 ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 3 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 36 || quatslice2(0,2,2) != -9 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 12 || quatslice2(0,3,2) != 15 || quatslice2(0,3,3) != -18 || + quatslice2(0,4,0) != 21 || quatslice2(0,4,1) != 84 || quatslice2(0,4,2) != 27 || quatslice2(0,4,3) != 30 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 3 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -6 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -9 || quatslice2(1,3,1) != 12 || quatslice2(1,3,2) != 15 || quatslice2(1,3,3) != 99 || + quatslice2(1,4,0) != 21 || quatslice2(1,4,1) != -24 || quatslice2(1,4,2) != 27 || quatslice2(1,4,3) != 33) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + initialize(); + + // Floating point scaling the 2nd quatslice + { + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + quatslice2.scale(0.5); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 18UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 0 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 6 || quatslice2(0,2,2) != -1 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 2 || quatslice2(0,3,2) != 2 || quatslice2(0,3,3) != -3 || + quatslice2(0,4,0) != 3 || quatslice2(0,4,1) != 14 || quatslice2(0,4,2) != 4 || quatslice2(0,4,3) != 5 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 0 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -1 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -1 || quatslice2(1,3,1) != 2 || quatslice2(1,3,2) != 2 || quatslice2(1,3,3) != 16 || + quatslice2(1,4,0) != 3 || quatslice2(1,4,1) != -4 || quatslice2(1,4,2) != 4 || quatslice2(1,4,3) != 5) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed self-scaling operation\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 3 0 0 )\n( -6 0 -9 0 )\n( 0 12 15 -18 )\n( 21 -24 27 30 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the QuatSlice function call operator. // -// if( it != end ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Scalar/iterator addition failed\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +// \return void +// \exception std::runtime_error Error detected. // -// // Testing assignment via Iterator -// { -// test_ = "assignment via Iterator"; +// This function performs a test of adding and accessing elements via the function call operator +// of the QuatSlice specialization. In case an error is detected, a \a std::runtime_error exception +// is thrown. +*/ +void DenseGeneralTest::testFunctionCall() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "QuatSlice::operator()"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + // Assignment to the element at index (0,1) + quatslice1(0,1,2) = 9; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 21UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 5 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -8 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (2,2) + quatslice1(1,3,2) = 0; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -8 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (4,1) + quatslice1(1,4,1) = -9; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 1 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + + // Addition assignment to the element at index (0,1) + quatslice1(0,0,1) += -3; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != -2 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Subtraction assignment to the element at index (2,0) + quatslice1(0,2,0) -= 6; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 21UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != -2 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -6 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Multiplication assignment to the element at index (4,0) + quatslice1(1,4,0) *= -3; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 21UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != -2 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -6 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) !=-21 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Division assignment to the element at index (3,3) + quatslice1(1,3,3) /= 2; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 21UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != -2 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 9 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -6 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 16 || + quatslice1(1,4,0) !=-21 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the QuatSlice at() operator. // -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// int value = 6; +// \return void +// \exception std::runtime_error Error detected. // -// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { -// *it = value++; -// } +// This function performs a test of adding and accessing elements via the at() operator +// of the QuatSlice specialization. In case an error is detected, a \a std::runtime_error exception +// is thrown. +*/ +void DenseGeneralTest::testAt() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "QuatSlice::at()"; + + initialize(); + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + // Assignment to the element at index (0,1) + quatslice1.at(0,0,1) = 9; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 9 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 5 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -8 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of 1st dense quatslice failed\n" + << " Details:\n" + << " Result:\n" + << quatslice1 << "\n" + << " Expected result:\n(( 0 1 0 0 ) ( 0 0 " + "0 0 ) ( 0 12 -3 0 ) ( 0 4 5 -6 " + ") ( 7 28 9 10 ) )\n(( 0 0 0 0 ) ( " + " 0 1 0 0 ) ( -2 0 0 0 ) ( -3 4 5 " + " 33 ) ( 7 -8 9 11 ) )\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (2,2) + quatslice1.at(1,3,2) = 0; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 19UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 9 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -8 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Assignment to the element at index (4,1) + quatslice1.at(1,4,1) = -9; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 19UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 9 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + + // Addition assignment to the element at index (0,1) + quatslice1.at(0,0,1) += -3; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 19UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 6 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != 0 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Subtraction assignment to the element at index (2,0) + quatslice1.at(0,2,0) -= 6; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 6 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -6 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) != 7 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Multiplication assignment to the element at index (4,0) + quatslice1.at(1,4,0) *= -3; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 6 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -6 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 33 || + quatslice1(1,4,0) !=-21 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Division assignment to the element at index (3,3) + quatslice1.at(1,3,3) /= 2; + + checkPages ( quatslice1, 2UL ); + checkRows ( quatslice1, 5UL ); + checkColumns ( quatslice1, 4UL ); + checkCapacity( quatslice1, 40UL ); + checkNonZeros( quatslice1, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice1(0,0,0) != 0 || quatslice1(0,0,1) != 6 || quatslice1(0,0,2) != 0 || quatslice1(0,0,3) != 0 || + quatslice1(0,1,0) != 0 || quatslice1(0,1,1) != 0 || quatslice1(0,1,2) != 0 || quatslice1(0,1,3) != 0 || + quatslice1(0,2,0) != -6 || quatslice1(0,2,1) != 12 || quatslice1(0,2,2) != -3 || quatslice1(0,2,3) != 0 || + quatslice1(0,3,0) != 0 || quatslice1(0,3,1) != 4 || quatslice1(0,3,2) != 5 || quatslice1(0,3,3) != -6 || + quatslice1(0,4,0) != 7 || quatslice1(0,4,1) != 28 || quatslice1(0,4,2) != 9 || quatslice1(0,4,3) != 10 || + quatslice1(1,0,0) != 0 || quatslice1(1,0,1) != 0 || quatslice1(1,0,2) != 0 || quatslice1(1,0,3) != 0 || + quatslice1(1,1,0) != 0 || quatslice1(1,1,1) != 1 || quatslice1(1,1,2) != 0 || quatslice1(1,1,3) != 0 || + quatslice1(1,2,0) != -2 || quatslice1(1,2,1) != 0 || quatslice1(1,2,2) != 0 || quatslice1(1,2,3) != 0 || + quatslice1(1,3,0) != -3 || quatslice1(1,3,1) != 4 || quatslice1(1,3,2) != 0 || quatslice1(1,3,3) != 16 || + quatslice1(1,4,0) !=-21 || quatslice1(1,4,1) != -9 || quatslice1(1,4,2) != 9 || quatslice1(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice1 << "\n" + << " Expected result:\n(( 0 9 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the QuatSlice iterator implementation. // -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 6 || quatslice2(4,1) != 7 || quatslice2(4,2) != 8 || quatslice2(4,3) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } +// \return void +// \exception std::runtime_error Error detected. // -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 6 || quat_(1,4,1) != 7 || quat_(1,4,2) != 8 || quat_(1,4,3) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 6 7 8 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +// This function performs a test of the iterator implementation of the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testIterator() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + initialize(); + + // Testing the Iterator default constructor + { + test_ = "Iterator default constructor"; + + RT::Iterator it{}; + + if( it != RT::Iterator() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator default constructor\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing the ConstIterator default constructor + { + test_ = "ConstIterator default constructor"; + + RT::ConstIterator it{}; + + if( it != RT::ConstIterator() ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator default constructor\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing conversion from Iterator to ConstIterator + { + test_ = "Iterator/ConstIterator conversion"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + RT::ConstIterator it( begin( quatslice2, 1UL, 2UL ) ); + + if( it == end( quatslice2, 1UL, 2UL ) || *it != -2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Failed iterator conversion detected\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 1st quatslice via Iterator (end-begin) + { + test_ = "Iterator subtraction (end-begin)"; + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + const ptrdiff_t number( end( quatslice1, 1UL, 2UL ) - begin( quatslice1, 1UL, 2UL ) ); + + if( number != 4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: 4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 1st quatslice via Iterator (begin-end) + { + test_ = "Iterator subtraction (begin-end)"; + + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + const ptrdiff_t number( begin( quatslice1, 1UL, 2UL ) - end( quatslice1, 1UL, 2UL ) ); + + if( number != -4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: -4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 2nd quatslice via ConstIterator (end-begin) + { + test_ = "ConstIterator subtraction (end-begin)"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + const ptrdiff_t number( cend( quatslice2, 1UL, 2UL ) - cbegin( quatslice2, 1UL, 2UL ) ); + + if( number != 4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: 4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Counting the number of elements in 2nd quatslice via ConstIterator (begin-end) + { + test_ = "ConstIterator subtraction (begin-end)"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + const ptrdiff_t number( cbegin( quatslice2, 1UL, 2UL ) - cend( quatslice2, 1UL, 2UL ) ); + + if( number != -4L ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid number of elements detected\n" + << " Details:\n" + << " Number of elements : " << number << "\n" + << " Expected number of elements: -4\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing read-only access via ConstIterator + { + test_ = "read-only access via ConstIterator"; + + RT quatslice3 = blaze::quatslice( quat_, 0UL ); + RT::ConstIterator it ( cbegin( quatslice3, 0UL, 4UL ) ); + RT::ConstIterator end( cend( quatslice3, 0UL, 4UL ) ); + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid initial iterator detected\n"; + throw std::runtime_error( oss.str() ); + } + + ++it; + + if( it == end || *it != -8 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator pre-increment failed\n"; + throw std::runtime_error( oss.str() ); + } + + --it; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator pre-decrement failed\n"; + throw std::runtime_error( oss.str() ); + } + + it++; + + if( it == end || *it != -8 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator post-increment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it--; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator post-decrement failed\n"; + throw std::runtime_error( oss.str() ); + } + + it += 2UL; + + if( it == end || *it != 9 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator addition assignment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it -= 2UL; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator subtraction assignment failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = it + 3UL; + + if( it == end || *it != 10 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator/scalar addition failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = it - 3UL; + + if( it == end || *it != 7 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator/scalar subtraction failed\n"; + throw std::runtime_error( oss.str() ); + } + + it = 4UL + it; + + if( it != end ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Scalar/iterator addition failed\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing assignment via Iterator + { + test_ = "assignment via Iterator"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + int value = 6; + + for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + *it = value++; + } + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 6 || quatslice2(0,3,1) != 7 || quatslice2(0,3,2) != 8 || quatslice2(0,3,3) != 9 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } // // // Testing addition assignment via Iterator -// { +// {std::cout << quat_ << "\n***********\n"; // test_ = "addition assignment via Iterator"; // // RT quatslice2 = blaze::quatslice( quat_, 1UL ); @@ -3756,8 +3179,8 @@ void DenseGeneralTest::testConstructors() // throw std::runtime_error( oss.str() ); // } // } -// } -//} + } +} ////************************************************************************************************* // // @@ -5159,27 +4582,67 @@ void DenseGeneralTest::testConstructors() void DenseGeneralTest::initialize() { // Initializing the quatslice-major dynamic quaternion - //quat_.reset(); - //quat_(0,1,1) = 1; - //quat_(0,2,0) = -2; - //quat_(0,2,2) = -3; - //quat_(0,3,1) = 4; - //quat_(0,3,2) = 5; - //quat_(0,3,3) = -6; - //quat_(0,4,0) = 7; - //quat_(0,4,1) = -8; - //quat_(0,4,2) = 9; - //quat_(0,4,3) = 10; - //quat_(1,1,1) = 1; - //quat_(1,2,0) = -2; - //quat_(1,2,2) = -3; - //quat_(1,3,1) = 4; - //quat_(1,3,2) = 5; - //quat_(1,3,3) = -6; - //quat_(1,4,0) = 7; - //quat_(1,4,1) = -8; - //quat_(1,4,2) = 9; - //quat_(1,4,3) = 10; + quat_.reset(); + quat_(0,0,1,1) = 1; + quat_(0,0,2,0) = -2; + quat_(0,0,2,2) = -3; + quat_(0,0,3,1) = 4; + quat_(0,0,3,2) = 5; + quat_(0,0,3,3) = -6; + quat_(0,0,4,0) = 7; + quat_(0,0,4,1) = -8; + quat_(0,0,4,2) = 9; + quat_(0,0,4,3) = 10; + quat_(0,1,1,1) = 1; + quat_(0,1,2,0) = -2; + quat_(0,1,2,2) = 13; + quat_(0,1,3,1) = 4; + quat_(0,1,3,2) = 5; + quat_(0,1,3,3) = -6; + quat_(0,1,4,0) = 7; + quat_(0,1,4,1) = -8; + quat_(0,1,4,2) = 9; + quat_(0,1,4,3) = 10; + quat_(1,0,0,1) = 1; + quat_(1,0,2,1) = 12; + quat_(1,0,2,2) = -3; + quat_(1,0,3,1) = 4; + quat_(1,0,3,2) = 5; + quat_(1,0,3,3) = -6; + quat_(1,0,4,0) = 7; + quat_(1,0,4,1) = 28; + quat_(1,0,4,2) = 9; + quat_(1,0,4,3) = 10; + quat_(1,1,1,1) = 1; + quat_(1,1,2,0) = -2; + quat_(1,1,3,0) = -3; + quat_(1,1,3,1) = 4; + quat_(1,1,3,2) = 5; + quat_(1,1,3,3) = 33; + quat_(1,1,4,0) = 7; + quat_(1,1,4,1) = -8; + quat_(1,1,4,2) = 9; + quat_(1,1,4,3) = 11; + quat_(2,0,1,1) = 1; + quat_(2,0,2,0) = -2; + quat_(2,0,2,2) = -3; + quat_(2,0,2,3) = 4; + quat_(2,0,3,2) = 5; + quat_(2,0,3,3) = 2; + quat_(2,0,4,0) = 7; + quat_(2,0,4,1) = -8; + quat_(2,0,4,2) = 9; + quat_(2,0,4,3) = 10; + quat_(2,1,1,1) = 1; + quat_(2,1,2,0) = 62; + quat_(2,1,2,2) = -3; + quat_(2,1,3,1) = 5; + quat_(2,1,3,2) = 15; + quat_(2,1,3,3) = 16; + quat_(2,1,4,0) = -7; + quat_(2,1,4,1) = -8; + quat_(2,1,4,2) = 19; + quat_(2,1,4,3) = 10; } //************************************************************************************************* From be2da017e5769b9320777fe58c2e5bfa4274ae32 Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Wed, 3 Jul 2019 13:33:46 -0500 Subject: [PATCH 10/14] working towards running the DenseGeneral test --- blaze_tensor/Math.h | 2 + blaze_tensor/math/DynamicArray.h | 4 +- blaze_tensor/math/constraints/Array.h | 6 +- blaze_tensor/math/dense/CustomArray.h | 4 +- blaze_tensor/math/dense/DenseArray.h | 2 +- blaze_tensor/math/dense/DynamicArray.h | 385 ++- blaze_tensor/math/expressions/Array.h | 1 + .../math/expressions/DArrReduceExpr.h | 1376 +++++++++ .../typetraits/{IsArray.h => IsNdArray.h} | 36 +- blaze_tensor/math/views/DilatedSubtensor.h | 5 +- blaze_tensor/math/views/Subtensor.h | 2 - blaze_tensor/math/views/quatslice/Dense.h | 9 +- blaze_tensor/util/ArrayForEach.h | 2 +- .../mathtest/quatslice/DenseGeneralTest.h | 10 +- .../customarray/AlignedPaddedTest1.cpp | 1 + .../src/mathtest/densearray/GeneralTest.cpp | 1 + .../mathtest/quatslice/DenseGeneralTest.cpp | 2520 ++++++++--------- 17 files changed, 2755 insertions(+), 1611 deletions(-) create mode 100644 blaze_tensor/math/expressions/DArrReduceExpr.h rename blaze_tensor/math/typetraits/{IsArray.h => IsNdArray.h} (80%) diff --git a/blaze_tensor/Math.h b/blaze_tensor/Math.h index e95ee93..995b414 100644 --- a/blaze_tensor/Math.h +++ b/blaze_tensor/Math.h @@ -45,7 +45,9 @@ #include #include +#include #include +#include #include #include #include diff --git a/blaze_tensor/math/DynamicArray.h b/blaze_tensor/math/DynamicArray.h index 43e3aa6..424edc0 100644 --- a/blaze_tensor/math/DynamicArray.h +++ b/blaze_tensor/math/DynamicArray.h @@ -115,7 +115,7 @@ template< typename... Dims > inline const DynamicArray Rand< DynamicArray >::generate( Dims... dims ) const { - DynamicArray array( dims... ); + DynamicArray array( dims... ); randomize( array ); return array; } @@ -139,7 +139,7 @@ template< typename Arg, typename... Dims > // Min/max argument type inline const DynamicArray Rand< DynamicArray >::generate( const Arg& min, const Arg& max, Dims... dims ) const { - DynamicArray array( dims... ); + DynamicArray array( dims... ); randomize( array, min, max ); return array; } diff --git a/blaze_tensor/math/constraints/Array.h b/blaze_tensor/math/constraints/Array.h index de9ca77..ee9527d 100644 --- a/blaze_tensor/math/constraints/Array.h +++ b/blaze_tensor/math/constraints/Array.h @@ -41,7 +41,7 @@ // Includes //************************************************************************************************* -#include +#include namespace blaze { @@ -60,7 +60,7 @@ namespace blaze { // is created. */ #define BLAZE_CONSTRAINT_MUST_BE_ARRAY_TYPE(T) \ - static_assert( ::blaze::IsArray_v, "Non-array type detected" ) + static_assert( ::blaze::IsNdArray_v, "Non-array type detected" ) //************************************************************************************************* @@ -80,7 +80,7 @@ namespace blaze { // is created. */ #define BLAZE_CONSTRAINT_MUST_NOT_BE_ARRAY_TYPE(T) \ - static_assert( !::blaze::IsArray_v, "Array type detected" ) + static_assert( !::blaze::IsNdArray_v, "Array type detected" ) //************************************************************************************************* } // namespace blaze diff --git a/blaze_tensor/math/dense/CustomArray.h b/blaze_tensor/math/dense/CustomArray.h index ba96635..847602e 100644 --- a/blaze_tensor/math/dense/CustomArray.h +++ b/blaze_tensor/math/dense/CustomArray.h @@ -1,6 +1,6 @@ //================================================================================================= /*! -// \file blaze_array/math/dense/CustomArray.h +// \file blaze_tensor/math/dense/CustomArray.h // \brief Header file for the implementation of a customizable array // // Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved @@ -52,7 +52,7 @@ #include #include #include -#include +#include namespace blaze { diff --git a/blaze_tensor/math/dense/DenseArray.h b/blaze_tensor/math/dense/DenseArray.h index 9e38205..1504f44 100644 --- a/blaze_tensor/math/dense/DenseArray.h +++ b/blaze_tensor/math/dense/DenseArray.h @@ -72,7 +72,7 @@ // #include #include #include -//#include +#include #include #include // #include diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index ccfb257..17393f7 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -60,6 +60,7 @@ #include #include +#include #include #include #include @@ -69,7 +70,7 @@ #include //#include #include -#include +#include #include #include #include @@ -443,28 +444,28 @@ class DynamicArray BLAZE_ALWAYS_INLINE void stream( const SIMDType& value, Dims... dims ) noexcept; template< typename MT > - inline auto assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v >; + inline auto assign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedAssign_v >*/; - template< typename MT > - inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; + //template< typename MT > + //inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; template< typename MT > - inline auto addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; + inline auto addAssign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedAddAssign_v >*/; - template< typename MT > - inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; + //template< typename MT > + //inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; template< typename MT > - inline auto subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; + inline auto subAssign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedSubAssign_v >*/; - template< typename MT > - inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; + //template< typename MT > + //inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; template< typename MT > - inline auto schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; + inline auto schurAssign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedSchurAssign_v >*/; - template< typename MT > - inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; + //template< typename MT > + //inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; //@} //********************************************************************************************** @@ -647,7 +648,7 @@ inline DynamicArray::DynamicArray( const Other* array, Dims... dims ) { BLAZE_STATIC_ASSERT( N == sizeof...( dims ) ); - if( IsNothrowMoveAssignable_v< ValueType > ) { + if( IsNothrowMoveAssignable_v< Type > ) { ArrayForEach2( dims_, nn_, [&]( size_t i, size_t j ) { v_[j] = std::move( array[i] ); } ); @@ -888,6 +889,7 @@ inline typename DynamicArray::Reference ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); + MAYBE_UNUSED( indices ); #endif return v_[index( dims... )]; @@ -920,6 +922,7 @@ inline typename DynamicArray::ConstReference ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); + MAYBE_UNUSED( indices ); #endif return v_[index( dims... )]; @@ -2054,6 +2057,7 @@ inline size_t DynamicArray::capacity( size_t i, Dims... dims ) const no ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); + MAYBE_UNUSED( indices ); #endif MAYBE_UNUSED( dims... ); @@ -2107,6 +2111,7 @@ inline size_t DynamicArray::nonZeros( size_t i, Dims... dims ) const ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { BLAZE_USER_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); + MAYBE_UNUSED( indices ); #endif const size_t jstart = row_index( i, dims... ); @@ -2358,7 +2363,7 @@ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array inline void DynamicArray::shrinkToFit() { - if( ( l_ * o_ * m_ * nn_ ) < capacity_ ) { + if( calcCapacity() < capacity_ ) { DynamicArray( *this ).swap( *this ); } } @@ -2466,7 +2471,7 @@ inline size_t DynamicArray::row_index( size_t i, Dims... dims ) const n { BLAZE_STATIC_ASSERT( N - 2 == sizeof...( dims ) ); - size_t indices[] = { dims..., i, 0 }; + size_t indices[] = { static_cast(dims)..., i, 0UL }; size_t idx = 0UL; for( size_t i = N - 1; i > 1; --i ) { @@ -2976,6 +2981,7 @@ BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); + MAYBE_UNUSED( indices ); #endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" ); @@ -3016,6 +3022,7 @@ BLAZE_ALWAYS_INLINE typename DynamicArray::SIMDType ArrayDimForEach( dims_, [&]( size_t i, size_t dim ) { BLAZE_INTERNAL_ASSERT( indices[N - i - 1] < dim, "Invalid array access index" ); } ); + MAYBE_UNUSED( indices ); #endif BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" ); @@ -3191,7 +3198,7 @@ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::assign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedAssign_v > + //-> DisableIf_t< VectorizedAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); @@ -3217,20 +3224,20 @@ inline auto DynamicArray::assign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // The dimensionality of the array - , typename Type > // Data type of the array -template< typename MT > // Type of the right-hand side dense array -inline auto DynamicArray::assign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); - - constexpr bool remainder( !usePadding || !IsPadded_v ); - - const size_t jpos( ( remainder )?( dims_[0] & size_t(-SIMDSIZE) ):( dims_[0] ) ); - BLAZE_INTERNAL_ASSERT( !remainder || ( dims_[0] - ( dims_[0] % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); +//template< size_t N // The dimensionality of the array +// , typename Type > // Data type of the array +//template< typename MT > // Type of the right-hand side dense array +//inline auto DynamicArray::assign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +// +// constexpr bool remainder( !usePadding || !IsPadded_v ); +// +// const size_t jpos( ( remainder )?( dims_[0] & size_t(-SIMDSIZE) ):( dims_[0] ) ); +// BLAZE_INTERNAL_ASSERT( !remainder || ( dims_[0] - ( dims_[0] % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" ); // if( usePadding && useStreaming && // ( o_*m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) && !(~rhs).isAliased( this ) ) @@ -3273,7 +3280,7 @@ inline auto DynamicArray::assign( const DenseArray& rhs ) // } // } // } -} +//} //************************************************************************************************* @@ -3292,28 +3299,17 @@ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::addAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedAddAssign_v > + //-> DisableIf_t< VectorizedAddAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); -// for (size_t k=0UL; k const& dims ) { + v_[i] += ( ~rhs )( dims ); + } ); } //************************************************************************************************* @@ -3329,46 +3325,46 @@ inline auto DynamicArray::addAssign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // The dimensionality of the array - , typename Type > // Data type of the array -template< typename MT > // Type of the right-hand side dense array -inline auto DynamicArray::addAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedAddAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); - - constexpr bool remainder( !usePadding || !IsPadded_v ); - - for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); - - for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { - left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; - } - for (; j // Data type of the array +//template< typename MT > // Type of the right-hand side dense array +//inline auto DynamicArray::addAssign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedAddAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +// +// constexpr bool remainder( !usePadding || !IsPadded_v ); +// +// for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() + right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Data type of the array template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::subAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedSubAssign_v > + //-> DisableIf_t< VectorizedSubAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); -// for (size_t k=0UL; k const& dims ) { + v_[i] -= ( ~rhs )( dims ); + } ); } //************************************************************************************************* @@ -3424,47 +3409,47 @@ inline auto DynamicArray::subAssign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // The dimensionality of the array - , typename Type > // Data type of the array -template< typename MT > // Type of the right-hand side dense array -inline auto DynamicArray::subAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedSubAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); - - constexpr bool remainder( !usePadding || !IsPadded_v ); - - for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); - - for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { - left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; - } - for (; j // Data type of the array +//template< typename MT > // Type of the right-hand side dense array +//inline auto DynamicArray::subAssign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedSubAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +// +// constexpr bool remainder( !usePadding || !IsPadded_v ); +// +// for (size_t k=0UL; k right((~rhs).begin(i, k) + jbegin); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() - right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j // Data type of the array template< typename MT > // Type of the right-hand side dense array inline auto DynamicArray::schurAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedSchurAssign_v > + //-> DisableIf_t< VectorizedSchurAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); -// const size_t jpos( n_ & size_t(-2) ); -// BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" ); -// -// for (size_t k=0UL; k const& dims ) { + v_[i] *= ( ~rhs )( dims ); + } ); } //************************************************************************************************* @@ -3517,43 +3494,43 @@ inline auto DynamicArray::schurAssign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // The dimensionality of the array - , typename Type > // Data type of the array -template< typename MT > // Type of the right-hand side dense array -inline auto DynamicArray::schurAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedSchurAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); - - constexpr bool remainder( !usePadding || !IsPadded_v ); - - for (size_t k=0UL; k right((~rhs).begin(i, k)); - - for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { - left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; - left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; - } - for (; j // Data type of the array +//template< typename MT > // Type of the right-hand side dense array +//inline auto DynamicArray::schurAssign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedSchurAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +// +// constexpr bool remainder( !usePadding || !IsPadded_v ); +// +// for (size_t k=0UL; k right((~rhs).begin(i, k)); +// +// for (; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL) { +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// left.store(left.load() * right.load()); left += SIMDSIZE; right += SIMDSIZE; +// } +// for (; j #include +#include #include #include diff --git a/blaze_tensor/math/expressions/DArrReduceExpr.h b/blaze_tensor/math/expressions/DArrReduceExpr.h new file mode 100644 index 0000000..2c9b0bc --- /dev/null +++ b/blaze_tensor/math/expressions/DArrReduceExpr.h @@ -0,0 +1,1376 @@ +//================================================================================================= +/*! +// \file blaze/math/expressions/DArrReduceExpr.h +// \brief Header file for the dense array reduce expression +// +// Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved +// +// This file is part of the Blaze library. You can redistribute it and/or modify it under +// the terms of the New (Revised) BSD License. Redistribution and use in source and binary +// forms, with or without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// 3. Neither the names of the Blaze development group nor the names of its contributors +// may be used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +*/ +//================================================================================================= + +#ifndef _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRREDUCEEXPR_H_ +#define _BLAZE_TENSOR_MATH_EXPRESSIONS_DARRREDUCEEXPR_H_ + + +//************************************************************************************************* +// Includes +//************************************************************************************************* + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Base template for dense array reduction operations. +// \ingroup dense_array_expression +// +// The ReducedArray class represents the compile time expression for partial reduction operations +// of dense matrices. +*/ +template< typename MT // Type of the dense array + , typename OP // Type of the reduction operation + , size_t RF > // Reduction flag +class ReducedArray; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS TEMPLATE SPECIALIZATION FOR ARBITRARY REDUCTION OPERATIONS OF ARRAYS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Expression object for arbitrary dense array reduction operations. +// \ingroup dense_array_expression +// +// This specialization of the ReducedArray class template represents the compile time expression +// for row-wise reduction operations of dense matrices. +*/ +template< typename MT // Type of the dense array + , typename OP // Type of the reduction operation + , size_t R > // DImension along which to perform reduction +class ReducedArray + : public ArrReduceExpr< DenseArray< ReducedArray >, R > + , private Computation +{ + private: + //**Type definitions**************************************************************************** + using RT = ResultType_t; //!< Result type of the dense array expression. + using ET = ElementType_t; //!< Element type of the dense array expression. + //********************************************************************************************** + + //**Serial evaluation strategy****************************************************************** + //! Compilation switch for the serial evaluation strategy of the reduction expression. + /*! The \a useAssign compile time constant expression represents a compilation switch for + the serial evaluation strategy of the reduction expression. In case the dense array + operand requires an intermediate evaluation, \a useAssign will be set to 1 and the + reduction expression will be evaluated via the \a assign function family. Otherwise + \a useAssign will be set to 0 and the expression will be evaluated via the subscript + operator. */ + static constexpr bool useAssign = RequiresEvaluation_v; + + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + template< typename VT > + static constexpr bool UseAssign_v = useAssign; + /*! \endcond */ + //********************************************************************************************** + + //**Parallel evaluation strategy**************************************************************** + /*! \cond BLAZE_INTERNAL */ + //! Helper variable template for the explicit application of the SFINAE principle. + /*! This variable template is a helper for the selection of the parallel evaluation strategy. + In case the dense array operand is not SMP assignable and requires an intermediate + evaluation, the variable is set to 1 and the expression specific evaluation strategy + is selected. Otherwise the variable is set to 0 and the default strategy is chosen. */ + template< typename VT > + static constexpr bool UseSMPAssign_v = ( !MT::smpAssignable && useAssign ); + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + using This = ReducedArray; //!< Type of this ReducedArray instance. + using ResultType = ReduceTrait_t; //!< Result type for expression template evaluations. + using TransposeType = TransposeType_t; //!< Transpose type for expression template evaluations. + using ElementType = ElementType_t; //!< Resulting element type. + using SIMDType = SIMDTrait_t; //!< Resulting SIMD element type. + using ReturnType = const ElementType; //!< Return type for expression template evaluations. + + //! Data type for composite expression templates. + using CompositeType = If_t< useAssign, const ResultType, const ReducedArray& >; + + //! Composite type of the left-hand side dense array expression. + using Operand = If_t< IsExpression_v, const MT, const MT& >; + + //! Data type of the custom unary operation. + using Operation = OP; + //********************************************************************************************** + + //**ConstIterator class definition************************************************************** + /*!\brief Iterator over the elements of the dense array. + */ + class ConstIterator + { + public: + //**Type definitions************************************************************************* + using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category. + using ValueType = ElementType; //!< Type of the underlying elements. + using PointerType = ElementType*; //!< Pointer return type. + using ReferenceType = ElementType&; //!< Reference return type. + using DifferenceType = ptrdiff_t; //!< Difference between two iterators. + + // STL iterator requirements + using iterator_category = IteratorCategory; //!< The iterator category. + using value_type = ValueType; //!< Type of the underlying elements. + using pointer = PointerType; //!< Pointer return type. + using reference = ReferenceType; //!< Reference return type. + using difference_type = DifferenceType; //!< Difference between two iterators. + //******************************************************************************************* + + //**Constructor****************************************************************************** + /*!\brief Constructor for the ConstIterator class. + // + // \param dm The dense array operand of the reduction expression. + // \param i Index to the initial array page. + // \param i Index to the array row. + // \param op The reduction operation. + */ + explicit inline ConstIterator( Operand dm, size_t k, OP op ) + : dm_ ( dm ) // Dense array of the reduction expression + , k_ ( k ) // Index to the current array page + , op_ ( op ) // The reduction operation + {} + //******************************************************************************************* + + //**Addition assignment operator************************************************************* + /*!\brief Addition assignment operator. + // + // \param inc The increment of the iterator. + // \return The incremented iterator. + */ + inline ConstIterator& operator+=( size_t inc ) { + k_ += inc; + return *this; + } + //******************************************************************************************* + + //**Subtraction assignment operator********************************************************** + /*!\brief Subtraction assignment operator. + // + // \param dec The decrement of the iterator. + // \return The decremented iterator. + */ + inline ConstIterator& operator-=( size_t dec ) { + k_ -= dec; + return *this; + } + //******************************************************************************************* + + //**Prefix increment operator**************************************************************** + /*!\brief Pre-increment operator. + // + // \return Reference to the incremented iterator. + */ + inline ConstIterator& operator++() { + ++k_; + return *this; + } + //******************************************************************************************* + + //**Postfix increment operator*************************************************************** + /*!\brief Post-increment operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator++( int ) { + return ConstIterator( k_++ ); + } + //******************************************************************************************* + + //**Prefix decrement operator**************************************************************** + /*!\brief Pre-decrement operator. + // + // \return Reference to the decremented iterator. + */ + inline ConstIterator& operator--() { + --k_; + return *this; + } + //******************************************************************************************* + + //**Postfix decrement operator*************************************************************** + /*!\brief Post-decrement operator. + // + // \return The previous position of the iterator. + */ + inline const ConstIterator operator--( int ) { + return ConstIterator( k_-- ); + } + //******************************************************************************************* + + //**Element access operator****************************************************************** + /*!\brief Direct access to the element at the current iterator position. + // + // \return The resulting value. + */ + //inline ReturnType operator*() const { + // return reduce( arrayslice< R >( dm_, k_, unchecked ), op_ ); + //} + //******************************************************************************************* + + //**Equality operator************************************************************************ + /*!\brief Equality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators refer to the same element, \a false if not. + */ + inline bool operator==( const ConstIterator& rhs ) const { + return k_ == rhs.k_; + } + //******************************************************************************************* + + //**Inequality operator********************************************************************** + /*!\brief Inequality comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the iterators don't refer to the same element, \a false if they do. + */ + inline bool operator!=( const ConstIterator& rhs ) const { + return k_ != rhs.k_; + } + //******************************************************************************************* + + //**Less-than operator*********************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller, \a false if not. + */ + inline bool operator<( const ConstIterator& rhs ) const { + return k_ < rhs.k_; + } + //******************************************************************************************* + + //**Greater-than operator******************************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater, \a false if not. + */ + inline bool operator>( const ConstIterator& rhs ) const { + return !(*this <= rhs); + } + //******************************************************************************************* + + //**Less-or-equal-than operator************************************************************** + /*!\brief Less-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is smaller or equal, \a false if not. + */ + inline bool operator<=( const ConstIterator& rhs ) const { + return k_ <= rhs.k_; + } + //******************************************************************************************* + + //**Greater-or-equal-than operator*********************************************************** + /*!\brief Greater-than comparison between two ConstIterator objects. + // + // \param rhs The right-hand side iterator. + // \return \a true if the left-hand side iterator is greater or equal, \a false if not. + */ + inline bool operator>=( const ConstIterator& rhs ) const { + return !(*this < rhs); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Calculating the number of elements between two iterators. + // + // \param rhs The right-hand side iterator. + // \return The number of elements between the two iterators. + */ + inline DifferenceType operator-( const ConstIterator& rhs ) const { + return k_ - rhs.k_; + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between a ConstIterator and an integral value. + // + // \param it The iterator to be incremented. + // \param inc The number of elements the iterator is incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( const ConstIterator& it, size_t inc ) { + return ConstIterator( it.k_ + inc ); + } + //******************************************************************************************* + + //**Addition operator************************************************************************ + /*!\brief Addition between an integral value and a ConstIterator. + // + // \param inc The number of elements the iterator is incremented. + // \param it The iterator to be incremented. + // \return The incremented iterator. + */ + friend inline const ConstIterator operator+( size_t inc, const ConstIterator& it ) { + return ConstIterator( it.k_ + inc ); + } + //******************************************************************************************* + + //**Subtraction operator********************************************************************* + /*!\brief Subtraction between a ConstIterator and an integral value. + // + // \param it The iterator to be decremented. + // \param dec The number of elements the iterator is decremented. + // \return The decremented iterator. + */ + friend inline const ConstIterator operator-( const ConstIterator& it, size_t dec ) { + return ConstIterator( it.k_ - dec ); + } + //******************************************************************************************* + + private: + //**Member variables************************************************************************* + Operand dm_; //!< Dense array of the reduction expression. + size_t k_; //!< Index to the current array page. + OP op_; //!< The reduction operation. + //******************************************************************************************* + }; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + static constexpr bool simdEnabled = false; + + //! Compilation switch for the expression template assignment strategy. + static constexpr bool smpAssignable = MT::smpAssignable; + //********************************************************************************************** + + //**Constructor********************************************************************************* + /*!\brief Constructor for the ReducedArray class. + // + // \param dm The array operand of the reduction expression. + // \param op The reduction operation. + */ + explicit inline ReducedArray( const MT& dm, OP op ) noexcept + : dm_( dm ) // Dense array of the reduction expression + , op_( op ) // The reduction operation + {} + //********************************************************************************************** + + //**Subscript operator************************************************************************** + /*!\brief Subscript operator for the direct access to the array elements. + // + // \param index Access index. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + */ + //template< typename... Dims > + //inline ReturnType operator()( Dims... dims ) const { + // return reduce( arrayslice( dm_, dims..., unchecked ), op_ ); + //} + //********************************************************************************************** + + //**At function********************************************************************************* + /*!\brief Checked access to the array elements. + // + // \param index Access index. The index has to be in the range \f$[0..N-1]\f$. + // \return The resulting value. + // \exception std::out_of_range Invalid array access index. + */ + template< typename... Dims > + inline ReturnType at( Dims... dims ) const { + constexpr size_t indices[] = {dims...}; + + ArrayDimForEach( dm_.dimensions(), [&]( size_t i, size_t dim ) { + if( indices[i] >= dim ) { + BLAZE_THROW_OUT_OF_RANGE( "Invalid array access index" ); + } + } ); + return (*this)(dims...); + } + //********************************************************************************************** + + //**Begin function****************************************************************************** + /*!\brief Returns an iterator to the first element of the dense array. + // + // \return Iterator to the first element of the dense array. + */ + inline ConstIterator begin( size_t i ) const { + return ConstIterator( dm_, i, op_ ); + } + //********************************************************************************************** + + //**End function******************************************************************************** + /*!\brief Returns an iterator just past the last non-zero element of the dense array. + // + // \return Iterator just past the last non-zero element of the dense array. + */ + inline ConstIterator end( size_t i ) const { + return ConstIterator( dm_, i, op_ ); + } + //********************************************************************************************** + + //**Num_dimensions function******************************************************************************* + /*!\brief Returns the current number of dimensions of the array. + // + // \return The size of the array. + */ + inline static constexpr size_t num_dimensions() noexcept { + return RemoveCV_t>::num_dimensions(); + } + //********************************************************************************************** + + //**Dimensions function**************************************************************************** + /*!\brief Returns the current dimensions of the array. + // + // \return The dimensions of the array. + */ + inline decltype(auto) dimensions() const noexcept { + return dm_.dimensions(); + } + //********************************************************************************************** + + //**Pages function******************************************************************************* + /*!\brief Returns the current size/dimension of the array. + // + // \return The size of the array. + */ + template< size_t Dim > + inline size_t dimension() const noexcept { + return dm_.template dimension(); + } + //********************************************************************************************** + + //**Operand access****************************************************************************** + /*!\brief Returns the dense array operand. + // + // \return The dense array operand. + */ + inline Operand operand() const noexcept { + return dm_; + } + //********************************************************************************************** + + //**Operation access**************************************************************************** + /*!\brief Returns a copy of the reduction operation. + // + // \return A copy of the reduction operation. + */ + inline Operation operation() const { + return op_; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can alias with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case an aliasing effect is possible, \a false if not. + */ + template< typename T > + inline bool canAlias( const T* alias ) const noexcept { + return ( dm_.isAliased( alias ) ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression is aliased with the given address \a alias. + // + // \param alias The alias to be checked. + // \return \a true in case the given alias is contained in this expression, \a false if not. + */ + template< typename T > + inline bool isAliased( const T* alias ) const noexcept { + return ( dm_.isAliased( alias ) ); + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the operands of the expression are properly aligned in memory. + // + // \return \a true in case the operands are aligned, \a false if not. + */ + inline bool isAligned() const noexcept { + return false; + } + //********************************************************************************************** + + //********************************************************************************************** + /*!\brief Returns whether the expression can be used in SMP assignments. + // + // \return \a true in case the expression can be used in SMP assignments, \a false if not. + */ + inline bool canSMPAssign() const noexcept { + return dm_.canSMPAssign() || ( dimension<1>() * dimension<0>() > SMP_DMATREDUCE_THRESHOLD ); + } + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + Operand dm_; //!< Dense array of the reduction expression. + Operation op_; //!< The reduction operation. + //********************************************************************************************** + + //**Assignment to tensors*********************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be assigned. + // \return void + // + // This function implements the performance optimized assignment of a row-wise row-major + // dense array reduction expression to a array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression specific + // parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto assign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + assign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Addition assignment to tensors************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Addition assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be added. + // \return void + // + // This function implements the performance optimized addition assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto addAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + addAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Subtraction assignment to tensors*********************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Subtraction assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be subtracted. + // \return void + // + // This function implements the performance optimized subtraction assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto subAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + subAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Multiplication assignment to tensors******************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Multiplication assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be multiplied. + // \return void + // + // This function implements the performance optimized multiplication assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto multAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + multAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Division assignment to tensors************************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief Division assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression divisor. + // \return void + // + // This function implements the performance optimized division assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto divAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( serial( rhs.dm_ ) ); // Evaluation of the dense array operand + divAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP assignment to tensors******************************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP assignment of a row-wise dense array reduction operation to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be assigned. + // \return void + // + // This function implements the performance optimized SMP assignment of a row-wise row-major + // dense array reduction expression to a array. Due to the explicit application of the SFINAE + // principle, this function can only be selected by the compiler in case the expression specific + // parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP addition assignment to tensors********************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP addition assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be added. + // \return void + // + // This function implements the performance optimized SMP addition assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpAddAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpAddAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP subtraction assignment to tensors******************************************************* + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP subtraction assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be subtracted. + // \return void + // + // This function implements the performance optimized SMP subtraction assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpSubAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpSubAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP multiplication assignment to tensors**************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP multiplication assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression to be multiplied. + // \return void + // + // This function implements the performance optimized SMP multiplication assignment of a + // row-wise dense array reduction expression to a array. Due to the explicit + // application of the SFINAE principle, this function can only be selected by the compiler + // in case the expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpMultAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpMultAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**SMP division assignment to tensors********************************************************** + /*! \cond BLAZE_INTERNAL */ + /*!\brief SMP division assignment of a row-wise dense array reduction operation + // to a array. + // \ingroup dense_array + // + // \param lhs The target left-hand side array. + // \param rhs The right-hand side reduction expression divisor. + // \return void + // + // This function implements the performance optimized SMP division assignment of a row-wise + // dense array reduction expression to a array. Due to the explicit application + // of the SFINAE principle, this function can only be selected by the compiler in case the + // expression specific parallel evaluation strategy is selected. + */ + template< typename VT1 > // Type of the target dense array + friend inline auto smpDivAssign( Array& lhs, const ReducedArray& rhs ) + -> EnableIf_t< UseSMPAssign_v > + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).dimensions() == rhs.dimensions(), "Invalid number of elements" ); + + const RT tmp( rhs.dm_ ); // Evaluation of the dense array operand + smpDivAssign( ~lhs, reduce( tmp, rhs.op_ ) ); + } + /*! \endcond */ + //********************************************************************************************** + + //**Compile time checks************************************************************************* + /*! \cond BLAZE_INTERNAL */ + BLAZE_CONSTRAINT_MUST_BE_DENSE_ARRAY_TYPE( MT ); + /*! \endcond */ + //********************************************************************************************** +}; +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Auxiliary helper struct for the dense array reduction operation. +// \ingroup dense_array +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +struct ArrayHelper +{ + //**Type definitions**************************************************************************** + //! Composite type of the dense array expression. + using CT = RemoveReference_t< CompositeType_t >; + + //! Element type of the dense array expression. + using ET = ElementType_t; + + //! Definition of the HasSIMDEnabled type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasSIMDEnabled, simdEnabled ); + + //! Definition of the HasLoad type trait. + BLAZE_CREATE_HAS_DATA_OR_FUNCTION_MEMBER_TYPE_TRAIT( HasLoad, load ); + //********************************************************************************************** + + //********************************************************************************************** + static constexpr bool value = + ( CT::simdEnabled && + If_t< HasSIMDEnabled_v, GetSIMDEnabled, HasLoad >::value ); + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Default backend implementation of the reduction of a dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +// +// This function implements the performance optimized reduction operation for a dense +// array. Due to the explicit application of the SFINAE principle, this function can only be +// selected by the compiler in case vectorization cannot be applied. +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline ElementType_t darrayreduce( const DenseArray& dm, OP op ) +{ + using CT = CompositeType_t; + using ET = ElementType_t; + + constexpr size_t N = + RemoveCV_t< RemoveReference_t< decltype( ~dm ) > >::num_dimensions(); + + std::array< size_t, N > dims{}; + + if( ArrayDimAnyOf( ( ~dm ).dimensions(), + []( size_t, size_t dim ) { return dim == 0; } ) ) + return ET{}; + + if( ArrayDimAllOf( ( ~dm ).dimensions(), + []( size_t, size_t dim ) { return dim == 1; } ) ) + return ( ~dm )( dims ); + + CT tmp( ~dm ); + + BLAZE_INTERNAL_ASSERT( tmp.dimensions() == (~dm).dimensions(), "Invalid number of elements" ); + + ET redux{}; + + ArrayForEachGrouped( ( ~dm ).dimensions(), + [&]( std::array< size_t, N > const& dims ) { + redux = op( redux, tmp( dims ) ); + } ); + + return redux; +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Performs a custom reduction operation on the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the given dense array \a dm by means of the given reduction operation +// \a op: + + \code + blaze::DynamicArray A; + // ... Resizing and initialization + + const double totalsum1 = reduce( A, blaze::Add() ); + const double totalsum2 = reduce( A, []( double a, double b ){ return a + b; } ); + \endcode + +// As demonstrated in the example it is possible to pass any binary callable as custom reduction +// operation. However, for instance in the case of lambdas the vectorization of the reduction +// operation is compiler dependent and might not perform at peak performance. However, it is also +// possible to create vectorized custom operations. See \ref custom_operations for a detailed +// overview of the possibilities of custom operations. +// +// Please note that the evaluation order of the reduction operation is unspecified. Thus the +// behavior is non-deterministic if \a op is not associative or not commutative. Also, the +// operation is undefined if the given reduction operation modifies the values. +*/ +template< typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline decltype(auto) reduce( const DenseArray& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return darrayreduce( ~dm, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Backend implementation for custom reduction operations on dense matrices. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +*/ +template< size_t RF // Reduction flag + , typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline const ReducedArray reduce_backend( const DenseArray& dm, OP op ) +{ + return ReducedArray( ~dm, op ); +} +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Performs a custom reduction operation on the given dense array. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction computation. +// \param op The reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the rows or columns of the given dense array \a dm by means of the +// given reduction operation \a op. In case the reduction flag \a RF is set to \a blaze::columnwise, +// the elements of the array are reduced column-wise and the result is a row array. In case +// \a RF is set to \a blaze::rowwise, the elements of the array are reduced row-wise and the +// result is a column array: + + \code + using blaze::columnwise; + + blaze::DynamicArray A; + blaze::DynamicMatrix colsum1, colsum2; + // ... Resizing and initialization + + colsum1 = reduce( A, blaze::Add() ); + colsum2 = reduce( A, []( double a, double b ){ return a + b; } ); + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A; + blaze::DynamicMatrix rowsum1, rowsum2; + // ... Resizing and initialization + + rowsum1 = reduce( A, blaze::Add() ); + rowsum2 = reduce( A, []( double a, double b ){ return a + b; } ); + \endcode + +// As demonstrated in the examples it is possible to pass any binary callable as custom reduction +// operation. However, for instance in the case of lambdas the vectorization of the reduction +// operation is compiler dependent and might not perform at peak performance. However, it is also +// possible to create vectorized custom operations. See \ref custom_operations for a detailed +// overview of the possibilities of custom operations. +// +// Please note that the evaluation order of the reduction operation is unspecified. Thus the +// behavior is non-deterministic if \a op is not associative or not commutative. Also, the +// operation is undefined if the given reduction operation modifies the values. +*/ +template< size_t RF // Reduction flag + , typename MT // Type of the dense array + , typename OP > // Type of the reduction operation +inline decltype(auto) reduce( const DenseArray& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce_backend( ~dm, op ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of addition. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the given dense array \a dm by means of addition: + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalsum = sum( A ); // Results in 10 + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) sum( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Add() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of addition. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the rows or columns of the given dense array \a dm by means of +// addition. In case the reduction flag \a RF is set to \a blaze::columnwise, the elements of +// the array are reduced column-wise and the result is a row array. In case \a RF is set to +// \a blaze::rowwise, the elements of the array are reduced row-wise and the result is a +// column array: + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colsum; + + colsum = sum( A ); // Results in ( 2, 3, 6 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowsum; + + rowsum = sum( A ); // Results in ( 3, 8 ) + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) sum( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Add() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of multiplication. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the given dense array \a dm by means of multiplication: + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalprod = prod( A ); // Results in 24 + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) prod( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Mult() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Reduces the given dense array by means of multiplication. +// \ingroup dense_array +// +// \param dm The given dense array for the reduction operation. +// \return The result of the reduction operation. +// +// This function reduces the rows or columns of the given dense array \a dm by means of +// multiplication. In case the reduction flag \a RF is set to \a blaze::columnwise, the elements +// of the array are reduced column-wise and the result is a row array. In case \a RF is set to +// \a blaze::rowwise, the elements of the array are reduced row-wise and the result is a column +// array: + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colprod; + + colprod = prod( A ); // Results in ( 1, 0, 8 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowprod; + + rowprod = prod( A ); // Results in ( 0, 12 ) + \endcode + +// Please note that the evaluation order of the reduction operation is unspecified. +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) prod( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Mult() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the smallest element of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The smallest dense array element. +// +// This function returns the smallest element of the given dense array. This function can only +// be used for element types that support the smaller-than relationship. In case the given array +// currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in +// case of fundamental data types). + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalmin = min( A ); // Results in 1 + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) min( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Min() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the smallest element of each row/columns of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The smallest elements in each row/column. +// +// This function returns the smallest element of each row/column of the given dense array \a dm. +// In case the reduction flag \a RF is set to \a blaze::columnwise, a row array containing the +// smallest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a +// column array containing the smallest element of each row is returned. + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colmin; + + colmin = min( A ); // Results in ( 1, 0, 2 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowmin; + + rowmin = min( A ); // Results in ( 0, 1 ) + \endcode +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) min( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Min() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the largest element of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The largest dense array element. +// +// This function returns the largest element of the given dense array. This function can only +// be used for element types that support the smaller-than relationship. In case the given martix +// currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in +// case of fundamental data types). + + \code + blaze::DynamicArray A{ { 1, 2 }, { 3, 4 } }; + + const int totalmax = max( A ); // Results in 4 + \endcode +*/ +template< typename MT > // Type of the dense array +inline decltype(auto) max( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Max() ); +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the largest element of each row/columns of the dense array. +// \ingroup dense_array +// +// \param dm The given dense array. +// \return The largest elements in each row/column. +// +// This function returns the largest element of each row/column of the given dense array \a dm. +// In case the reduction flag \a RF is set to \a blaze::columnwise, a row array containing the +// largest element of each column is returned. In case \a RF is set to \a blaze::rowwise, a +// column array containing the largest element of each row is returned. + + \code + using blaze::columnwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix colmax; + + colmax = max( A ); // Results in ( 1, 3, 4 ) + \endcode + + \code + using blaze::rowwise; + + blaze::DynamicArray A{ { 1, 0, 2 }, { 1, 3, 4 } }; + blaze::DynamicMatrix rowmax; + + rowmax = max( A ); // Results in ( 2, 4 ) + \endcode +*/ +template< size_t RF // Reduction flag + , typename MT > // Type of the dense array +inline decltype(auto) max( const DenseArray& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return reduce( ~dm, Max() ); +} +//************************************************************************************************* + +} // namespace blaze + +#endif diff --git a/blaze_tensor/math/typetraits/IsArray.h b/blaze_tensor/math/typetraits/IsNdArray.h similarity index 80% rename from blaze_tensor/math/typetraits/IsArray.h rename to blaze_tensor/math/typetraits/IsNdArray.h index 2316e1a..c559d4f 100644 --- a/blaze_tensor/math/typetraits/IsArray.h +++ b/blaze_tensor/math/typetraits/IsNdArray.h @@ -1,7 +1,7 @@ //================================================================================================= /*! -// \file blaze_tensor/math/typetraits/IsArray.h -// \brief Header file for the IsArray type trait +// \file blaze_tensor/math/typetraits/IsNdArray.h +// \brief Header file for the IsNdArray type trait // // Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved // Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved @@ -33,8 +33,8 @@ */ //================================================================================================= -#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAY_H_ -#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISARRAY_H_ +#ifndef _BLAZE_TENSOR_MATH_TYPETRAITS_ISNDARRAY_H_ +#define _BLAZE_TENSOR_MATH_TYPETRAITS_ISNDARRAY_H_ //************************************************************************************************* @@ -57,11 +57,11 @@ namespace blaze { //************************************************************************************************* /*! \cond BLAZE_INTERNAL */ -/*!\brief Auxiliary helper struct for the IsArray type trait. +/*!\brief Auxiliary helper struct for the IsNdArray type trait. // \ingroup math_type_traits */ template< typename T > -struct IsArrayHelper +struct IsNdArrayHelper { private: //********************************************************************************************** @@ -94,34 +94,34 @@ struct IsArrayHelper // class derives from \a FalseType. \code - blaze::IsArray< const DynamicArray >::Type // Results in TrueType - blaze::IsArray< StaticVector >::value // Evaluates to 0 - blaze::IsArray< const DynamicVector >::Type // Results in FalseType - blaze::IsArray< volatile CompressedVector > // Is derived from FalseType + blaze::IsNdArray< const DynamicArray >::Type // Results in TrueType + blaze::IsNdArray< StaticVector >::value // Evaluates to 0 + blaze::IsNdArray< const DynamicVector >::Type // Results in FalseType + blaze::IsNdArray< volatile CompressedVector > // Is derived from FalseType \endcode */ template< typename T > -struct IsArray - : public IsArrayHelper::Type +struct IsNdArray + : public IsNdArrayHelper::Type {}; //************************************************************************************************* //************************************************************************************************* -/*!\brief Auxiliary variable template for the IsArray type trait. +/*!\brief Auxiliary variable template for the IsNdArray type trait. // \ingroup type_traits // -// The IsArray_v variable template provides a convenient shortcut to access the nested \a value -// of the IsArray class template. For instance, given the type \a T the following two statements +// The IsNdArray_v variable template provides a convenient shortcut to access the nested \a value +// of the IsNdArray class template. For instance, given the type \a T the following two statements // are identical: \code - constexpr bool value1 = blaze::IsArray::value; - constexpr bool value2 = blaze::IsArray_v; + constexpr bool value1 = blaze::IsNdArray::value; + constexpr bool value2 = blaze::IsNdArray_v; \endcode */ template< typename T > -constexpr bool IsArray_v = IsArray::value; +constexpr bool IsNdArray_v = IsNdArray::value; //************************************************************************************************* } // namespace blaze diff --git a/blaze_tensor/math/views/DilatedSubtensor.h b/blaze_tensor/math/views/DilatedSubtensor.h index 0e64b07..7b96965 100644 --- a/blaze_tensor/math/views/DilatedSubtensor.h +++ b/blaze_tensor/math/views/DilatedSubtensor.h @@ -346,10 +346,11 @@ inline decltype(auto) dilatedsubtensor( Tensor&& tensor, RSAs... args ) // Please note that this function creates an unaligned dense or sparse DilatedSubtensor. For instance, // the creation of the dense DilatedSubtensor is equivalent to the following function call: -************************************************************************************************* +*/ +//************************************************************************************************* -************************************************************************************************* +//************************************************************************************************* /*!\brief Creating a view on a specific DilatedSubtensor of the given tensor. // \ingroup DilatedSubtensor // diff --git a/blaze_tensor/math/views/Subtensor.h b/blaze_tensor/math/views/Subtensor.h index 28cc224..0c404c3 100644 --- a/blaze_tensor/math/views/Subtensor.h +++ b/blaze_tensor/math/views/Subtensor.h @@ -969,8 +969,6 @@ inline decltype(auto) subtensor( const TensMatSchurExpr& tensor, RSAs... arg { BLAZE_FUNCTION_TRACE; - using TT1 = RemoveReference_t< LeftOperand_t< TensorType_t > >; - const SubtensorData st( args... ); BLAZE_DECLTYPE_AUTO( left , (~tensor).leftOperand() ); diff --git a/blaze_tensor/math/views/quatslice/Dense.h b/blaze_tensor/math/views/quatslice/Dense.h index e087c82..32334f2 100644 --- a/blaze_tensor/math/views/quatslice/Dense.h +++ b/blaze_tensor/math/views/quatslice/Dense.h @@ -1264,7 +1264,7 @@ template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline size_t QuatSlice::nonZeros( size_t i, size_t k ) const { - return quaternion_.nonZeros( quat(), k, i ); + return quaternion_.nonZeros( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* @@ -1282,7 +1282,7 @@ inline void QuatSlice::reset() { for (size_t k = 0; k < pages(); ++k) { for (size_t i = 0; i < rows(); ++i) { - quaternion_.reset( quat(), k, i ); + quaternion_.reset( i, quat(), k ); } } } @@ -1298,9 +1298,10 @@ inline void QuatSlice::reset() */ template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments -inline void QuatSlice::reset( size_t i, size_t k ) +inline void QuatSlice::reset( size_t k, size_t i ) { - quaternion_.reset( quat(), k, i ); + std::cout << quat() << "\n***********\n"; + quaternion_.reset( i, quat(), k ); } /*! \endcond */ //************************************************************************************************* diff --git a/blaze_tensor/util/ArrayForEach.h b/blaze_tensor/util/ArrayForEach.h index afedd8a..e5a5b2a 100644 --- a/blaze_tensor/util/ArrayForEach.h +++ b/blaze_tensor/util/ArrayForEach.h @@ -1,6 +1,6 @@ //================================================================================================= /*! -// \file blaze/util/ArrayForEach.h +// \file blaze_tensor/util/ArrayForEach.h // \brief Header file for the ArrayForEach function // // Copyright (C) 2012-2019 Klaus Iglberger - All Rights Reserved diff --git a/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h b/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h index 64427c8..202dbac 100644 --- a/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h +++ b/blazetest/blazetest/mathtest/quatslice/DenseGeneralTest.h @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -107,11 +108,10 @@ class DenseGeneralTest void testIsDefault(); void testIsSame(); void testSubtensor(); - //void testRow(); - //void testRows(); - //void testColumn(); - //void testColumns(); - //void testBand(); + void testPageslice(); + void testRowslice(); + void testColumnslice(); + template< typename Type > void checkSize( const Type& quatslice, size_t expectedSize ) const; diff --git a/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp b/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp index d25c632..1611e18 100644 --- a/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp +++ b/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp @@ -53,6 +53,7 @@ #include #include +#include #include namespace blazetest { diff --git a/blazetest/src/mathtest/densearray/GeneralTest.cpp b/blazetest/src/mathtest/densearray/GeneralTest.cpp index 0388885..22aca1e 100644 --- a/blazetest/src/mathtest/densearray/GeneralTest.cpp +++ b/blazetest/src/mathtest/densearray/GeneralTest.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include diff --git a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp index 219156f..e197b49 100644 --- a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp +++ b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp @@ -85,16 +85,15 @@ DenseGeneralTest::DenseGeneralTest() testFunctionCall(); testAt(); testIterator(); - //testNonZeros(); - //testReset(); - //testClear(); - //testIsDefault(); - //testIsSame(); - //testSubquaternion(); - //testRow(); - //testRows(); - //testColumn(); - //testColumns(); + testNonZeros(); + testReset(); + testClear(); + testIsDefault(); + testIsSame(); + testSubtensor(); + testPageslice(); + testRowslice(); + testColumnslice(); } //************************************************************************************************* @@ -2964,807 +2963,756 @@ void DenseGeneralTest::testIterator() throw std::runtime_error( oss.str() ); } } -// -// // Testing addition assignment via Iterator -// {std::cout << quat_ << "\n***********\n"; -// test_ = "addition assignment via Iterator"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// int value = 2; -// -// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { -// *it += value++; -// } -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 8 || quatslice2(4,1) != 10 || quatslice2(4,2) != 12 || quatslice2(4,3) != 14 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 8 10 12 14 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 8 || quat_(1,4,1) != 10 || quat_(1,4,2) != 12 || quat_(1,4,3) != 14 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Addition assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 8 10 12 14 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Testing subtraction assignment via Iterator -// { -// test_ = "subtraction assignment via Iterator"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// int value = 2; -// -// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { -// *it -= value++; -// } -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 6 || quatslice2(4,1) != 7 || quatslice2(4,2) != 8 || quatslice2(4,3) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 6 || quat_(1,4,1) != 7 || quat_(1,4,2) != 8 || quat_(1,4,3) != 9 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subtraction assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 6 7 8 9 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Testing multiplication assignment via Iterator -// { -// test_ = "multiplication assignment via Iterator"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// int value = 1; -// -// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { -// *it *= value++; -// } -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 6 || quatslice2(4,1) != 14 || quatslice2(4,2) != 24 || quatslice2(4,3) != 36 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 14 24 36 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 6 || quat_(1,4,1) != 14 || quat_(1,4,2) != 24 || quat_(1,4,3) != 36 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Multiplication assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 6 14 24 36 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Testing division assignment via Iterator -// { -// test_ = "division assignment via Iterator"; -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// for( RT::Iterator it=begin( quatslice2, 4UL ); it!=end( quatslice2, 4UL ); ++it ) { -// *it /= 2; -// } -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 3 || quatslice2(4,1) != 7 || quatslice2(4,2) != 12 || quatslice2(4,3) != 18 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Division assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 3 7 12 18 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 1 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != -2 || quat_(1,2,1) != 0 || quat_(1,2,2) != -3 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 4 || quat_(1,3,2) != 5 || quat_(1,3,3) != -6 || -// quat_(1,4,0) != 3 || quat_(1,4,1) != 7 || quat_(1,4,2) != 12 || quat_(1,4,3) != 18 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Division assignment via iterator failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 0 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 3 7 12 18 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } + + // Testing addition assignment via Iterator + { + test_ = "addition assignment via Iterator"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + int value = 2; + + for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + *it += value++; + } + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 8 || quatslice2(0,3,1) != 10 || quatslice2(0,3,2) != 12 || quatslice2(0,3,3) != 14 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Addition assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 8 10 12 14 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing subtraction assignment via Iterator + { + test_ = "subtraction assignment via Iterator"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + int value = 2; + + for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + *it -= value++; + } + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 6 || quatslice2(0,3,1) != 7 || quatslice2(0,3,2) != 8 || quatslice2(0,3,3) != 9 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subtraction assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 7 8 9 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing multiplication assignment via Iterator + { + test_ = "multiplication assignment via Iterator"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + int value = 1; + + for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + *it *= value++; + } + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 6 || quatslice2(0,3,1) != 14 || quatslice2(0,3,2) != 24 || quatslice2(0,3,3) != 36 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Multiplication assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 6 14 24 36 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Testing division assignment via Iterator + { + test_ = "division assignment via Iterator"; + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + + for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + *it /= 2; + } + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 3 || quatslice2(0,3,1) != 7 || quatslice2(0,3,2) != 12 || quatslice2(0,3,3) != 18 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Division assignment via iterator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 3 7 12 18 ))\n"; + throw std::runtime_error( oss.str() ); + } + } } } -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c nonZeros() member function of the QuatSlice specialization. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c nonZeros() member function of the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testNonZeros() -//{ -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "QuatSlice::nonZeros()"; -// -// initialize(); -// -// // Initialization check -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != -3 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Initialization failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Changing the number of non-zeros via the dense quatslice -// quatslice2(2, 2) = 0; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 19UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// // Changing the number of non-zeros via the dense quaternion -// quat_(1,3,0) = 5; -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 10UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 20UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 5 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Matrix function call operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 5 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c reset() member function of the QuatSlice specialization. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c reset() member function of the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testReset() -//{ -// using blaze::reset; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "QuatSlice::reset()"; -// -// // Resetting a single element in quatslice 3 -// { -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// reset( quatslice2(2, 2) ); -// -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 19UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Reset operator failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Resetting the 1st quatslice (lvalue) -// { -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// reset( quatslice2 ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 0UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || -// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Reset operation of 1st quatslice failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Resetting the 1st quatslice (rvalue) -// { -// initialize(); -// -// reset( blaze::quatslice( quat_, 1UL ) ); -// -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Reset operation of 1st quatslice failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c clear() function with the QuatSlice specialization. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c clear() function with the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testClear() -//{ -// using blaze::clear; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "clear() function"; -// -// // Clearing a single element in quatslice 1 -// { -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// clear( quatslice2(2, 2) ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 9UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 19UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 1 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != -2 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 4 || quatslice2(3,2) != 5 || quatslice2(3,3) != -6 || -// quatslice2(4,0) != 7 || quatslice2(4,1) != -8 || quatslice2(4,2) != 9 || quatslice2(4,3) != 10 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Clear operation failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Clearing the 3rd quatslice (lvalue) -// { -// initialize(); -// -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// clear( quatslice2 ); -// -// checkRows ( quatslice2, 5UL ); -// checkColumns ( quatslice2, 4UL ); -// checkCapacity( quatslice2, 20UL ); -// checkNonZeros( quatslice2, 0UL ); -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quatslice2(0,0) != 0 || quatslice2(0,1) != 0 || quatslice2(0,2) != 0 || quatslice2(0,3) != 0 || -// quatslice2(1,0) != 0 || quatslice2(1,1) != 0 || quatslice2(1,2) != 0 || quatslice2(1,3) != 0 || -// quatslice2(2,0) != 0 || quatslice2(2,1) != 0 || quatslice2(2,2) != 0 || quatslice2(2,3) != 0 || -// quatslice2(3,0) != 0 || quatslice2(3,1) != 0 || quatslice2(3,2) != 0 || quatslice2(3,3) != 0 || -// quatslice2(4,0) != 0 || quatslice2(4,1) != 0 || quatslice2(4,2) != 0 || quatslice2(4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Clear operation of 3rd quatslice failed\n" -// << " Details:\n" -// << " Result:\n" << quatslice2 << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // Clearing the 4th quatslice (rvalue) -// { -// initialize(); -// -// clear( blaze::quatslice( quat_, 1UL ) ); -// -// checkRows ( quat_, 5UL ); -// checkColumns ( quat_, 4UL ); -// checkQuats ( quat_, 2UL ); -// checkNonZeros( quat_, 10UL ); -// -// if( quat_(0,0,0) != 0 || quat_(0,0,1) != 0 || quat_(0,0,2) != 0 || quat_(0,0,3) != 0 || -// quat_(0,1,0) != 0 || quat_(0,1,1) != 1 || quat_(0,1,2) != 0 || quat_(0,1,3) != 0 || -// quat_(0,2,0) != -2 || quat_(0,2,1) != 0 || quat_(0,2,2) != -3 || quat_(0,2,3) != 0 || -// quat_(0,3,0) != 0 || quat_(0,3,1) != 4 || quat_(0,3,2) != 5 || quat_(0,3,3) != -6 || -// quat_(0,4,0) != 7 || quat_(0,4,1) != -8 || quat_(0,4,2) != 9 || quat_(0,4,3) != 10 || -// quat_(1,0,0) != 0 || quat_(1,0,1) != 0 || quat_(1,0,2) != 0 || quat_(1,0,3) != 0 || -// quat_(1,1,0) != 0 || quat_(1,1,1) != 0 || quat_(1,1,2) != 0 || quat_(1,1,3) != 0 || -// quat_(1,2,0) != 0 || quat_(1,2,1) != 0 || quat_(1,2,2) != 0 || quat_(1,2,3) != 0 || -// quat_(1,3,0) != 0 || quat_(1,3,1) != 0 || quat_(1,3,2) != 0 || quat_(1,3,3) != 0 || -// quat_(1,4,0) != 0 || quat_(1,4,1) != 0 || quat_(1,4,2) != 0 || quat_(1,4,3) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Clear operation of 1st quatslice failed\n" -// << " Details:\n" -// << " Result:\n" << quat_ << "\n" -// << " Expected result:\n(( 0 0 0 0 )\n" -// " ( 0 1 0 0 )\n" -// " ( -2 0 -3 0 )\n" -// " ( 0 4 5 -6 )\n" -// " ( 7 -8 9 10 ))\n" -// "(( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 )\n" -// " ( 0 0 0 0 ))\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c isDefault() function with the QuatSlice specialization. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c isDefault() function with the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testIsDefault() -//{ -// using blaze::isDefault; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "isDefault() function"; -// -// initialize(); -// -// // isDefault with default quatslice -// { -// RT quatslice0 = blaze::quatslice( quat_, 0UL ); -// quatslice0 = 0; -// -// if( isDefault( quatslice0(0, 0) ) != true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isDefault evaluation\n" -// << " Details:\n" -// << " QuatSlice element: " << quatslice0(0, 0) << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( isDefault( quatslice0 ) != true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isDefault evaluation\n" -// << " Details:\n" -// << " QuatSlice:\n" << quatslice0 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isDefault with non-default quatslice -// { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// -// if( isDefault( quatslice1(1, 1) ) != false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isDefault evaluation\n" -// << " Details:\n" -// << " QuatSlice element: " << quatslice1(1, 1) << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( isDefault( quatslice1 ) != false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isDefault evaluation\n" -// << " Details:\n" -// << " QuatSlice:\n" << quatslice1 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c isSame() function with the QuatSlice specialization. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c isSame() function with the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testIsSame() -//{ -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "isSame() function"; -// -// // isSame with quatching quatslices -// { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// if( blaze::isSame( quatslice1, quatslice2 ) == false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First quatslice:\n" << quatslice1 << "\n" -// << " Second quatslice:\n" << quatslice2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with non-quatching quatslices -// { -// RT quatslice1 = blaze::quatslice( quat_, 0UL ); -// RT quatslice2 = blaze::quatslice( quat_, 1UL ); -// -// quatslice1 = 42; -// -// if( blaze::isSame( quatslice1, quatslice2 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First quatslice:\n" << quatslice1 << "\n" -// << " Second quatslice:\n" << quatslice2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with quatslice and quatching subquaternion -// { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// auto sv = blaze::subquaternion( quatslice1, 0UL, 0UL, 5UL, 4UL ); -// -// if( blaze::isSame( quatslice1, sv ) == false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " Dense quatslice:\n" << quatslice1 << "\n" -// << " Dense subquaternion:\n" << sv << "\n"; -// throw std::runtime_error( oss.str() ); -// } +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c nonZeros() member function of the QuatSlice specialization. // -// if( blaze::isSame( sv, quatslice1 ) == false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " Dense quatslice:\n" << quatslice1 << "\n" -// << " Dense subquaternion:\n" << sv << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +// \return void +// \exception std::runtime_error Error detected. // -// // isSame with quatslice and non-quatching subquaternion (different size) -// { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// auto sv = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 3UL ); +// This function performs a test of the \c nonZeros() member function of the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testNonZeros() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "QuatSlice::nonZeros()"; + + initialize(); + + // Initialization check + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 20UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 4 || quatslice2(0,3,2) != 5 || quatslice2(0,3,3) != -6 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Initialization failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 -3 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Changing the number of non-zeros via the dense quatslice + quatslice2(1, 3, 2) = 0; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 19UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 4 || quatslice2(0,3,2) != 5 || quatslice2(0,3,3) != -6 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 0 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + + // Changing the number of non-zeros via the dense quaternion + quat_(1,1,3,0) = 0; + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 18UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 4 || quatslice2(0,3,2) != 5 || quatslice2(0,3,3) != -6 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 10 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != 0 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 0 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Matrix function call operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 5 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c reset() member function of the QuatSlice specialization. // -// if( blaze::isSame( quatslice1, sv ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " Dense quatslice:\n" << quatslice1 << "\n" -// << " Dense subquaternion:\n" << sv << "\n"; -// throw std::runtime_error( oss.str() ); -// } +// \return void +// \exception std::runtime_error Error detected. // -// if( blaze::isSame( sv, quatslice1 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " Dense quatslice:\n" << quatslice1 << "\n" -// << " Dense subquaternion:\n" << sv << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +// This function performs a test of the \c reset() member function of the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testReset() +{ + using blaze::reset; + + + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "QuatSlice::reset()"; + + // Resetting a single element in quatslice 3 + { + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + reset( quatslice2(0,4,3) ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 19UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 4 || quatslice2(0,3,2) != 5 || quatslice2(0,3,3) != -6 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 0 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Resetting the 1st quatslice (lvalue) + { + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + reset( quatslice2 ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 0UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 0 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 0 || quatslice2(0,2,2) != 0 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 0 || quatslice2(0,3,2) != 0 || quatslice2(0,3,3) != 0 || + quatslice2(0,4,0) != 0 || quatslice2(0,4,1) != 0 || quatslice2(0,4,2) != 0 || quatslice2(0,4,3) != 0 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 0 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != 0 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != 0 || quatslice2(1,3,1) != 0 || quatslice2(1,3,2) != 0 || quatslice2(1,3,3) != 0 || + quatslice2(1,4,0) != 0 || quatslice2(1,4,1) != 0 || quatslice2(1,4,2) != 0 || quatslice2(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation of 1st quatslice failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Resetting the 1st quatslice (rvalue) + { + initialize(); + + reset( blaze::quatslice( quat_, 1UL ) ); + + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 0 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 0 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 0 || quat_(1,0,2,1) != 0 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 0 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 0 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != 0 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 0 || + quat_(1,1,4,0) != 0 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation of 1st quatslice failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c clear() function with the QuatSlice specialization. // -// // isSame with quatslice and non-quatching subquaternion (different offset) -// { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// auto sv = blaze::subquaternion( quatslice1, 1UL, 1UL, 3UL, 3UL ); +// \return void +// \exception std::runtime_error Error detected. // -// if( blaze::isSame( quatslice1, sv ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " Dense quatslice:\n" << quatslice1 << "\n" -// << " Dense subquaternion:\n" << sv << "\n"; -// throw std::runtime_error( oss.str() ); -// } +// This function performs a test of the \c clear() function with the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testClear() +{ + using blaze::clear; + + + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "clear() function"; + + // Clearing a single element in quatslice 1 + { + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + clear( quatslice2(0,4,3) ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 19UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 1 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 12 || quatslice2(0,2,2) != -3 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 4 || quatslice2(0,3,2) != 5 || quatslice2(0,3,3) != -6 || + quatslice2(0,4,0) != 7 || quatslice2(0,4,1) != 28 || quatslice2(0,4,2) != 9 || quatslice2(0,4,3) != 0 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 1 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != -2 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != -3 || quatslice2(1,3,1) != 4 || quatslice2(1,3,2) != 5 || quatslice2(1,3,3) != 33 || + quatslice2(1,4,0) != 7 || quatslice2(1,4,1) != -8 || quatslice2(1,4,2) != 9 || quatslice2(1,4,3) != 11 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operator failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 1 0 0 )\n( -2 0 0 0 )\n( 0 4 5 -6 )\n( 7 -8 9 10 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Clearing the 3rd quatslice (lvalue) + { + initialize(); + + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + clear( quatslice2 ); + + checkPages ( quatslice2, 2UL ); + checkRows ( quatslice2, 5UL ); + checkColumns ( quatslice2, 4UL ); + checkCapacity( quatslice2, 40UL ); + checkNonZeros( quatslice2, 0UL ); + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quatslice2(0,0,0) != 0 || quatslice2(0,0,1) != 0 || quatslice2(0,0,2) != 0 || quatslice2(0,0,3) != 0 || + quatslice2(0,1,0) != 0 || quatslice2(0,1,1) != 0 || quatslice2(0,1,2) != 0 || quatslice2(0,1,3) != 0 || + quatslice2(0,2,0) != 0 || quatslice2(0,2,1) != 0 || quatslice2(0,2,2) != 0 || quatslice2(0,2,3) != 0 || + quatslice2(0,3,0) != 0 || quatslice2(0,3,1) != 0 || quatslice2(0,3,2) != 0 || quatslice2(0,3,3) != 0 || + quatslice2(0,4,0) != 0 || quatslice2(0,4,1) != 0 || quatslice2(0,4,2) != 0 || quatslice2(0,4,3) != 0 || + quatslice2(1,0,0) != 0 || quatslice2(1,0,1) != 0 || quatslice2(1,0,2) != 0 || quatslice2(1,0,3) != 0 || + quatslice2(1,1,0) != 0 || quatslice2(1,1,1) != 0 || quatslice2(1,1,2) != 0 || quatslice2(1,1,3) != 0 || + quatslice2(1,2,0) != 0 || quatslice2(1,2,1) != 0 || quatslice2(1,2,2) != 0 || quatslice2(1,2,3) != 0 || + quatslice2(1,3,0) != 0 || quatslice2(1,3,1) != 0 || quatslice2(1,3,2) != 0 || quatslice2(1,3,3) != 0 || + quatslice2(1,4,0) != 0 || quatslice2(1,4,1) != 0 || quatslice2(1,4,2) != 0 || quatslice2(1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation of 1st quatslice failed\n" + << " Details:\n" + << " Result:\n" << quatslice2 << "\n" + << " Expected result:\n(( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 )\n( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + + // Clearing the 4th quatslice (rvalue) + { + initialize(); + + clear( blaze::quatslice( quat_, 1UL ) ); + + checkPages ( quat_, 2UL ); + checkRows ( quat_, 5UL ); + checkColumns ( quat_, 4UL ); + checkQuats ( quat_, 3UL ); + + if( quat_(1,0,0,0) != 0 || quat_(1,0,0,1) != 0 || quat_(1,0,0,2) != 0 || quat_(1,0,0,3) != 0 || + quat_(1,0,1,0) != 0 || quat_(1,0,1,1) != 0 || quat_(1,0,1,2) != 0 || quat_(1,0,1,3) != 0 || + quat_(1,0,2,0) != 0 || quat_(1,0,2,1) != 0 || quat_(1,0,2,2) != 0 || quat_(1,0,2,3) != 0 || + quat_(1,0,3,0) != 0 || quat_(1,0,3,1) != 0 || quat_(1,0,3,2) != 0 || quat_(1,0,3,3) != 0 || + quat_(1,0,4,0) != 0 || quat_(1,0,4,1) != 0 || quat_(1,0,4,2) != 0 || quat_(1,0,4,3) != 0 || + quat_(1,1,0,0) != 0 || quat_(1,1,0,1) != 0 || quat_(1,1,0,2) != 0 || quat_(1,1,0,3) != 0 || + quat_(1,1,1,0) != 0 || quat_(1,1,1,1) != 0 || quat_(1,1,1,2) != 0 || quat_(1,1,1,3) != 0 || + quat_(1,1,2,0) != 0 || quat_(1,1,2,1) != 0 || quat_(1,1,2,2) != 0 || quat_(1,1,2,3) != 0 || + quat_(1,1,3,0) != 0 || quat_(1,1,3,1) != 0 || quat_(1,1,3,2) != 0 || quat_(1,1,3,3) != 0 || + quat_(1,1,4,0) != 0 || quat_(1,1,4,1) != 0 || quat_(1,1,4,2) != 0 || quat_(1,1,4,3) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Reset operation of 1st quatslice failed\n" + << " Details:\n" + << " Result:\n" << quat_ << "\n" + << " Expected result:\n(( 0 0 0 0 )\n" + " ( 0 1 0 0 )\n" + " ( -2 0 -3 0 )\n" + " ( 0 4 5 -6 )\n" + " ( 7 -8 9 10 ))\n" + "(( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 )\n" + " ( 0 0 0 0 ))\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isDefault() function with the QuatSlice specialization. // -// if( blaze::isSame( sv, quatslice1 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " Dense quatslice:\n" << quatslice1 << "\n" -// << " Dense subquaternion:\n" << sv << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +// \return void +// \exception std::runtime_error Error detected. // -// // isSame with quatching quatslices on a common subquaternion -// { -// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); -// auto quatslice1 = blaze::quatslice( sm, 1UL ); -// auto quatslice2 = blaze::quatslice( sm, 1UL ); +// This function performs a test of the \c isDefault() function with the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testIsDefault() +{ + using blaze::isDefault; + + + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "isDefault() function"; + + initialize(); + + // isDefault with default quatslice + { + RT quatslice0 = blaze::quatslice( quat_, 0UL ); + quatslice0 = 0; + + if( isDefault( quatslice0(0, 1, 0) ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " QuatSlice element: " << quatslice0(0, 1, 0) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( isDefault( quatslice0 ) != true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " QuatSlice:\n" << quatslice0 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isDefault with non-default quatslice + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + + if( isDefault( quatslice1(0, 0, 1) ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " QuatSlice element: " << quatslice1(0, 0, 1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( isDefault( quatslice1 ) != false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isDefault evaluation\n" + << " Details:\n" + << " QuatSlice:\n" << quatslice1 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c isSame() function with the QuatSlice specialization. // -// if( blaze::isSame( quatslice1, quatslice2 ) == false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First quatslice:\n" << quatslice1 << "\n" -// << " Second quatslice:\n" << quatslice2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } +// \return void +// \exception std::runtime_error Error detected. // -// // isSame with non-quatching quatslices on a common subquaternion +// This function performs a test of the \c isSame() function with the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testIsSame() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "isSame() function"; + + // isSame with matching quatslices + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + + if( blaze::isSame( quatslice1, quatslice2 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First quatslice:\n" << quatslice1 << "\n" + << " Second quatslice:\n" << quatslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with non-matching quatslices + { + RT quatslice1 = blaze::quatslice( quat_, 0UL ); + RT quatslice2 = blaze::quatslice( quat_, 1UL ); + + quatslice1 = 42; + + if( blaze::isSame( quatslice1, quatslice2 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " First quatslice:\n" << quatslice1 << "\n" + << " Second quatslice:\n" << quatslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with quatslice and matching subtensor + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + auto sv = blaze::subtensor( quatslice1, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); + + if( blaze::isSame( quatslice1, sv ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense quatslice:\n" << quatslice1 << "\n" + << " Dense subtensor:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( sv, quatslice1 ) == false ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense quatslice:\n" << quatslice1 << "\n" + << " Dense subtensor:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with quatslice and non-matching subtensor (different size) + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + auto sv = blaze::subtensor( quatslice1, 0UL, 0UL, 0UL, 1UL, 3UL, 3UL ); + + if( blaze::isSame( quatslice1, sv ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense quatslice:\n" << quatslice1 << "\n" + << " Dense subtensor:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( sv, quatslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense quatslice:\n" << quatslice1 << "\n" + << " Dense subtensor:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + // isSame with quatslice and non-matching subtensor (different offset) + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + auto sv = blaze::subtensor( quatslice1, 1UL, 1UL, 1UL, 1UL, 3UL, 3UL ); + + if( blaze::isSame( quatslice1, sv ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense quatslice:\n" << quatslice1 << "\n" + << " Dense subtensor:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( blaze::isSame( sv, quatslice1 ) == true ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Invalid isSame evaluation\n" + << " Details:\n" + << " Dense quatslice:\n" << quatslice1 << "\n" + << " Dense subtensor:\n" << sv << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + //// isSame with matching quatslices on a common subarray + //{ + // auto sm = blaze::subarray( quat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); + // auto quatslice1 = blaze::quatslice( sm, 1UL ); + // auto quatslice2 = blaze::quatslice( sm, 1UL ); + + // if( blaze::isSame( quatslice1, quatslice2 ) == false ) { + // std::ostringstream oss; + // oss << " Test: " << test_ << "\n" + // << " Error: Invalid isSame evaluation\n" + // << " Details:\n" + // << " First quatslice:\n" << quatslice1 << "\n" + // << " Second quatslice:\n" << quatslice2 << "\n"; + // throw std::runtime_error( oss.str() ); + // } + //} +// +// // isSame with non-matching quatslices on a common subarray // { -// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); +// auto sm = blaze::subarray( quat_, 0UL, 1UL, 1UL, 2UL, 3UL, 2UL ); // auto quatslice1 = blaze::quatslice( sm, 0UL ); // auto quatslice2 = blaze::quatslice( sm, 1UL ); // @@ -3779,9 +3727,9 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with quatching subquaternion on quaternion and subquaternion +// // isSame with matching subtensor on quaternion and subtensor // { -// auto sm = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto sm = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); // auto quatslice1 = blaze::quatslice( quat_, 1UL ); // auto quatslice2 = blaze::quatslice( sm , 0UL ); // @@ -3806,9 +3754,9 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with non-quatching quatslices on quaternion and subquaternion (different quatslice) +// // isSame with non-matching quatslices on quaternion and subtensor (different quatslice) // { -// auto sm = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto sm = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); // auto quatslice1 = blaze::quatslice( quat_, 0UL ); // auto quatslice2 = blaze::quatslice( sm , 0UL ); // @@ -3833,9 +3781,9 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with non-quatching quatslices on quaternion and subquaternion (different size) +// // isSame with non-matching quatslices on quaternion and subtensor (different size) // { -// auto sm = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 4UL, 3UL ); +// auto sm = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 4UL, 3UL ); // auto quatslice1 = blaze::quatslice( quat_, 1UL ); // auto quatslice2 = blaze::quatslice( sm , 0UL ); // @@ -3860,10 +3808,10 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with quatching quatslices on two subquaternions +// // isSame with matching quatslices on two subtensors // { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto sm1 = blaze::subtensor( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); // auto quatslice1 = blaze::quatslice( sm1, 1UL ); // auto quatslice2 = blaze::quatslice( sm2, 0UL ); // @@ -3888,10 +3836,10 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with non-quatching quatslices on two subquaternions (different quatslice) +// // isSame with non-matching quatslices on two subtensors (different quatslice) // { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto sm1 = blaze::subtensor( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); // auto quatslice1 = blaze::quatslice( sm1, 0UL ); // auto quatslice2 = blaze::quatslice( sm2, 0UL ); // @@ -3916,10 +3864,10 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with non-quatching quatslices on two subquaternions (different size) +// // isSame with non-matching quatslices on two subtensors (different size) // { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 4UL, 3UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto sm1 = blaze::subtensor( quat_, 0UL, 0UL, 0UL, 2UL, 4UL, 3UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); // auto quatslice1 = blaze::quatslice( sm1, 1UL ); // auto quatslice2 = blaze::quatslice( sm2, 0UL ); // @@ -3944,10 +3892,10 @@ void DenseGeneralTest::testIterator() // } // } // -// // isSame with non-quatching quatslices on two subquaternions (different offset) +// // isSame with non-matching quatslices on two subtensors (different offset) // { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 4UL, 2UL ); +// auto sm1 = blaze::subtensor( quat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 4UL, 2UL ); // auto quatslice1 = blaze::quatslice( sm1, 1UL ); // auto quatslice2 = blaze::quatslice( sm2, 0UL ); // @@ -3967,602 +3915,440 @@ void DenseGeneralTest::testIterator() // << " Error: Invalid isSame evaluation\n" // << " Details:\n" // << " First quatslice:\n" << quatslice1 << "\n" -// << " Second quatslice:\n" << quatslice2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with quatching quatslice subquatrices on a subquaternion -// { -// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); -// auto quatslice1 = blaze::quatslice( sm, 1UL ); -// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); -// auto sv2 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); -// -// if( blaze::isSame( sv1, sv2 ) == false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First subquaternion:\n" << sv1 << "\n" -// << " Second subquaternion:\n" << sv2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with non-quatching quatslice subquaternions on a subquaternion (different size) -// { -// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); -// auto quatslice1 = blaze::quatslice( sm, 1UL ); -// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); -// auto sv2 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 2UL ); -// -// if( blaze::isSame( sv1, sv2 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First subquaternion:\n" << sv1 << "\n" -// << " Second subquaternion:\n" << sv2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with non-quatching quatslice subquaternions on a subquaternion (different offset) -// { -// auto sm = blaze::subquaternion( quat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); -// auto quatslice1 = blaze::quatslice( sm, 1UL ); -// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 1UL ); -// auto sv2 = blaze::subquaternion( quatslice1, 0UL, 1UL, 2UL, 1UL ); -// -// if( blaze::isSame( sv1, sv2 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First subquaternion:\n" << sv1 << "\n" -// << " Second subquaternion:\n" << sv2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with quatching quatslice subquaternions on two subquaternions -// { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); -// auto quatslice1 = blaze::quatslice( sm1, 1UL ); -// auto quatslice2 = blaze::quatslice( sm2, 0UL ); -// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 2UL ); -// auto sv2 = blaze::subquaternion( quatslice2, 0UL, 0UL, 3UL, 2UL ); -// -// if( blaze::isSame( sv1, sv2 ) == false ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First subquaternion:\n" << sv1 << "\n" -// << " Second subquaternion:\n" << sv2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with non-quatching quatslice subquaternions on two subquaternions (different size) -// { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); -// auto quatslice1 = blaze::quatslice( sm1, 1UL ); -// auto quatslice2 = blaze::quatslice( sm2, 0UL ); -// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 2UL ); -// auto sv2 = blaze::subquaternion( quatslice2, 0UL, 0UL, 2UL, 2UL ); -// -// if( blaze::isSame( sv1, sv2 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First subquaternion:\n" << sv1 << "\n" -// << " Second subquaternion:\n" << sv2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// // isSame with non-quatching quatslice subquaternions on two subquaternions (different offset) -// { -// auto sm1 = blaze::subquaternion( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); -// auto sm2 = blaze::subquaternion( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); -// auto quatslice1 = blaze::quatslice( sm1, 1UL ); -// auto quatslice2 = blaze::quatslice( sm2, 0UL ); -// auto sv1 = blaze::subquaternion( quatslice1, 0UL, 0UL, 3UL, 2UL ); -// auto sv2 = blaze::subquaternion( quatslice2, 0UL, 1UL, 3UL, 2UL ); -// -// if( blaze::isSame( sv1, sv2 ) == true ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Invalid isSame evaluation\n" -// << " Details:\n" -// << " First subquaternion:\n" << sv1 << "\n" -// << " Second subquaternion:\n" << sv2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c subquaternion() function with the QuatSlice specialization. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c subquaternion() function used with the QuatSlice specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testSubquaternion() -//{ -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "subquaternion() function"; -// -// initialize(); -// -// { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// auto sm = blaze::subquaternion( quatslice1, 1UL, 1UL, 2UL, 3UL ); -// -// if( sm(0,0) != 1 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subscript operator access failed\n" -// << " Details:\n" -// << " Result: " << sm(0,0) << "\n" -// << " Expected result: 1\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( *sm.begin(1) != 0 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator access failed\n" -// << " Details:\n" -// << " Result: " << *sm.begin(1) << "\n" -// << " Expected result: 0\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// try { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// auto sm = blaze::subquaternion( quatslice1, 4UL, 0UL, 4UL, 4UL ); -// -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds subquaternion succeeded\n" -// << " Details:\n" -// << " Result:\n" << sm << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// -// try { -// RT quatslice1 = blaze::quatslice( quat_, 1UL ); -// auto sm = blaze::subquaternion( quatslice1, 0UL, 0UL, 2UL, 6UL ); -// -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds subquaternion succeeded\n" -// << " Details:\n" -// << " Result:\n" << sm << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// } -//} -////************************************************************************************************* -// -////************************************************************************************************* -///*!\brief Test of the \c row() function with the Subquaternion class template. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c row() function with the Subquaternion specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testRow() -//{ -// using blaze::quatslice; -// using blaze::row; -// using blaze::aligned; -// using blaze::unaligned; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "Quatslice row() function"; -// -// initialize(); -// -// { -// RT quatslice1 = quatslice( quat_, 0UL ); -// RT quatslice2 = quatslice( quat_, 1UL ); -// auto row1 = row( quatslice1, 1UL ); -// auto row2 = row( quatslice2, 1UL ); -// -// if( row1 != row2 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Row function failed\n" -// << " Details:\n" -// << " Result:\n" << row1 << "\n" -// << " Expected result:\n" << row2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( row1[1] != row2[1] ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subscript operator access failed\n" -// << " Details:\n" -// << " Result: " << row1[1] << "\n" -// << " Expected result: " << row2[1] << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( *row1.begin() != *row2.begin() ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator access failed\n" -// << " Details:\n" -// << " Result: " << *row1.begin() << "\n" -// << " Expected result: " << *row2.begin() << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// try { -// RT quatslice1 = quatslice( quat_, 0UL ); -// auto row8 = row( quatslice1, 8UL ); -// -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds row succeeded\n" -// << " Details:\n" -// << " Result:\n" << row8 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c rows() function with the Subquaternion class template. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c rows() function with the Subquaternion specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testRows() -//{ -// using blaze::quatslice; -// using blaze::rows; -// using blaze::aligned; -// using blaze::unaligned; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "Quatslice rows() function"; -// -// initialize(); -// -// { -// RT quatslice1 = quatslice( quat_, 0UL ); -// RT quatslice2 = quatslice( quat_, 1UL ); -// auto rs1 = rows( quatslice1, { 0UL, 2UL, 4UL, 3UL } ); -// auto rs2 = rows( quatslice2, { 0UL, 2UL, 4UL, 3UL } ); -// -// if( rs1 != rs2 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Rows function failed\n" -// << " Details:\n" -// << " Result:\n" << rs1 << "\n" -// << " Expected result:\n" << rs2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( rs1(1,1) != rs2(1,1) ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Function call operator access failed\n" -// << " Details:\n" -// << " Result: " << rs1(1,1) << "\n" -// << " Expected result: " << rs2(1,1) << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( *rs1.begin( 1UL ) != *rs2.begin( 1UL ) ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator access failed\n" -// << " Details:\n" -// << " Result: " << *rs1.begin( 1UL ) << "\n" -// << " Expected result: " << *rs2.begin( 1UL ) << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// try { -// RT quatslice1 = quatslice( quat_, 1UL ); -// auto rs = rows( quatslice1, { 8UL } ); -// -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds row selection succeeded\n" -// << " Details:\n" -// << " Result:\n" << rs << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c column() function with the Subquaternion class template. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c column() function with the Subquaternion specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testColumn() -//{ -// using blaze::quatslice; -// using blaze::column; -// using blaze::aligned; -// using blaze::unaligned; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "Quatslice column() function"; -// -// initialize(); -// -// { -// RT quatslice1 = quatslice( quat_, 0UL ); -// RT quatslice2 = quatslice( quat_, 1UL ); -// auto col1 = column( quatslice1, 1UL ); -// auto col2 = column( quatslice2, 1UL ); -// -// if( col1 != col2 ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Column function failed\n" -// << " Details:\n" -// << " Result:\n" << col1 << "\n" -// << " Expected result:\n" << col2 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( col1[1] != col2[1] ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Subscript operator access failed\n" -// << " Details:\n" -// << " Result: " << col1[1] << "\n" -// << " Expected result: " << col2[1] << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// -// if( *col1.begin() != *col2.begin() ) { -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Iterator access failed\n" -// << " Details:\n" -// << " Result: " << *col1.begin() << "\n" -// << " Expected result: " << *col2.begin() << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// } -// -// try { -// RT quatslice1 = quatslice( quat_, 0UL ); -// auto col16 = column( quatslice1, 16UL ); -// -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds column succeeded\n" -// << " Details:\n" -// << " Result:\n" << col16 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c columns() function with the Subquaternion class template. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c columns() function with the Subquaternion specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testColumns() -//{ -// using blaze::quatslice; -// using blaze::rows; -// using blaze::aligned; -// using blaze::unaligned; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "columns() function"; -// -// initialize(); +// << " Second quatslice:\n" << quatslice2 << "\n"; +// throw std::runtime_error( oss.str() ); +// } +// } // +// // isSame with matching quatslice subquatrices on a subtensor // { -// RT quatslice1 = quatslice( quat_, 0UL ); -// RT quatslice2 = quatslice( quat_, 1UL ); -// auto cs1 = columns( quatslice1, { 0UL, 2UL, 2UL, 3UL } ); -// auto cs2 = columns( quatslice2, { 0UL, 2UL, 2UL, 3UL } ); +// auto sm = blaze::subtensor( quat_, 0UL, 1UL, 2UL, 2UL, 4UL, 2UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto sv1 = blaze::subtensor( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// auto sv2 = blaze::subtensor( quatslice1, 0UL, 0UL, 2UL, 1UL ); // -// if( cs1 != cs2 ) { +// if( blaze::isSame( sv1, sv2 ) == false ) { // std::ostringstream oss; // oss << " Test: " << test_ << "\n" -// << " Error: Rows function failed\n" +// << " Error: Invalid isSame evaluation\n" // << " Details:\n" -// << " Result:\n" << cs1 << "\n" -// << " Expected result:\n" << cs2 << "\n"; +// << " First subtensor:\n" << sv1 << "\n" +// << " Second subtensor:\n" << sv2 << "\n"; // throw std::runtime_error( oss.str() ); // } +// } // -// if( cs1(1,1) != cs2(1,1) ) { +// // isSame with non-matching quatslice subtensors on a subtensor (different size) +// { +// auto sm = blaze::subtensor( quat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto sv1 = blaze::subtensor( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// auto sv2 = blaze::subtensor( quatslice1, 0UL, 0UL, 2UL, 2UL ); +// +// if( blaze::isSame( sv1, sv2 ) == true ) { // std::ostringstream oss; // oss << " Test: " << test_ << "\n" -// << " Error: Function call operator access failed\n" +// << " Error: Invalid isSame evaluation\n" // << " Details:\n" -// << " Result: " << cs1(1,1) << "\n" -// << " Expected result: " << cs2(1,1) << "\n"; +// << " First subtensor:\n" << sv1 << "\n" +// << " Second subtensor:\n" << sv2 << "\n"; // throw std::runtime_error( oss.str() ); // } +// } +// +// // isSame with non-matching quatslice subtensors on a subtensor (different offset) +// { +// auto sm = blaze::subtensor( quat_, 0UL, 1UL, 1UL, 2UL, 4UL, 3UL ); +// auto quatslice1 = blaze::quatslice( sm, 1UL ); +// auto sv1 = blaze::subtensor( quatslice1, 0UL, 0UL, 2UL, 1UL ); +// auto sv2 = blaze::subtensor( quatslice1, 0UL, 1UL, 2UL, 1UL ); // -// if( *cs1.begin( 1UL ) != *cs2.begin( 1UL ) ) { +// if( blaze::isSame( sv1, sv2 ) == true ) { // std::ostringstream oss; // oss << " Test: " << test_ << "\n" -// << " Error: Iterator access failed\n" +// << " Error: Invalid isSame evaluation\n" // << " Details:\n" -// << " Result: " << *cs1.begin( 1UL ) << "\n" -// << " Expected result: " << *cs2.begin( 1UL ) << "\n"; +// << " First subtensor:\n" << sv1 << "\n" +// << " Second subtensor:\n" << sv2 << "\n"; // throw std::runtime_error( oss.str() ); // } // } // -// try { -// RT quatslice1 = quatslice( quat_, 1UL ); -// auto cs = columns( quatslice1, { 16UL } ); -// -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds column selection succeeded\n" -// << " Details:\n" -// << " Result:\n" << cs << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// } -//} -////************************************************************************************************* -// -// -////************************************************************************************************* -///*!\brief Test of the \c band() function with the Subquaternion class template. -//// -//// \return void -//// \exception std::runtime_error Error detected. -//// -//// This function performs a test of the \c band() function with the Subquaternion specialization. -//// In case an error is detected, a \a std::runtime_error exception is thrown. -//*/ -//void DenseGeneralTest::testBand() -//{ -// using blaze::quatslice; -// using blaze::band; -// using blaze::aligned; -// using blaze::unaligned; -// -// -// //===================================================================================== -// // quaternion tests -// //===================================================================================== -// -// { -// test_ = "Quatslice band() function"; -// -// initialize(); -// +// // isSame with matching quatslice subtensors on two subtensors // { -// RT quatslice1 = quatslice( quat_, 0UL ); -// RT quatslice2 = quatslice( quat_, 1UL ); -// auto b1 = band( quatslice1, 1L ); -// auto b2 = band( quatslice2, 1L ); +// auto sm1 = blaze::subtensor( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// auto sv1 = blaze::subtensor( quatslice1, 0UL, 0UL, 3UL, 2UL ); +// auto sv2 = blaze::subtensor( quatslice2, 0UL, 0UL, 3UL, 2UL ); // -// if( b1 != b2 ) { +// if( blaze::isSame( sv1, sv2 ) == false ) { // std::ostringstream oss; // oss << " Test: " << test_ << "\n" -// << " Error: Band function failed\n" +// << " Error: Invalid isSame evaluation\n" // << " Details:\n" -// << " Result:\n" << b1 << "\n" -// << " Expected result:\n" << b2 << "\n"; +// << " First subtensor:\n" << sv1 << "\n" +// << " Second subtensor:\n" << sv2 << "\n"; // throw std::runtime_error( oss.str() ); // } +// } +// +// // isSame with non-matching quatslice subtensors on two subtensors (different size) +// { +// auto sm1 = blaze::subtensor( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// auto sv1 = blaze::subtensor( quatslice1, 0UL, 0UL, 3UL, 2UL ); +// auto sv2 = blaze::subtensor( quatslice2, 0UL, 0UL, 2UL, 2UL ); // -// if( b1[1] != b2[1] ) { +// if( blaze::isSame( sv1, sv2 ) == true ) { // std::ostringstream oss; // oss << " Test: " << test_ << "\n" -// << " Error: Subscript operator access failed\n" +// << " Error: Invalid isSame evaluation\n" // << " Details:\n" -// << " Result: " << b1[1] << "\n" -// << " Expected result: " << b2[1] << "\n"; +// << " First subtensor:\n" << sv1 << "\n" +// << " Second subtensor:\n" << sv2 << "\n"; // throw std::runtime_error( oss.str() ); // } +// } // -// if( *b1.begin() != *b2.begin() ) { +// // isSame with non-matching quatslice subtensors on two subtensors (different offset) +// { +// auto sm1 = blaze::subtensor( quat_, 0UL, 0UL, 0UL, 2UL, 5UL, 4UL ); +// auto sm2 = blaze::subtensor( quat_, 1UL, 0UL, 0UL, 1UL, 5UL, 4UL ); +// auto quatslice1 = blaze::quatslice( sm1, 1UL ); +// auto quatslice2 = blaze::quatslice( sm2, 0UL ); +// auto sv1 = blaze::subtensor( quatslice1, 0UL, 0UL, 3UL, 2UL ); +// auto sv2 = blaze::subtensor( quatslice2, 0UL, 1UL, 3UL, 2UL ); +// +// if( blaze::isSame( sv1, sv2 ) == true ) { // std::ostringstream oss; // oss << " Test: " << test_ << "\n" -// << " Error: Iterator access failed\n" +// << " Error: Invalid isSame evaluation\n" // << " Details:\n" -// << " Result: " << *b1.begin() << "\n" -// << " Expected result: " << *b2.begin() << "\n"; +// << " First subtensor:\n" << sv1 << "\n" +// << " Second subtensor:\n" << sv2 << "\n"; // throw std::runtime_error( oss.str() ); // } // } + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c subtensor() function with the QuatSlice specialization. // -// try { -// RT quatslice1 = quatslice( quat_, 1UL ); -// auto b8 = band( quatslice1, -8L ); +// \return void +// \exception std::runtime_error Error detected. // -// std::ostringstream oss; -// oss << " Test: " << test_ << "\n" -// << " Error: Setup of out-of-bounds band succeeded\n" -// << " Details:\n" -// << " Result:\n" << b8 << "\n"; -// throw std::runtime_error( oss.str() ); -// } -// catch( std::invalid_argument& ) {} -// } -//} -////************************************************************************************************* +// This function performs a test of the \c subtensor() function used with the QuatSlice specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testSubtensor() +{ + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "subtensor() function"; + + initialize(); + + { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + auto sm = blaze::subtensor( quatslice1, 1UL, 1UL, 1UL, 1UL, 3UL, 2UL ); + + if( sm(0,0,0) != 1 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << sm(0,0,0) << "\n" + << " Expected result: 1\n"; + throw std::runtime_error( oss.str() ); + } + + // sm.begin( page, row) + if( *sm.begin(0,1) != 0 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *sm.begin(1,0) << "\n" + << " Expected result: 0\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + auto sm = blaze::subtensor( quatslice1, 2UL, 4UL, 0UL, 1UL, 4UL, 4UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds subtensor succeeded\n" + << " Details:\n" + << " Result:\n" << sm << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + + try { + RT quatslice1 = blaze::quatslice( quat_, 1UL ); + auto sm = blaze::subtensor( quatslice1, 0UL, 0UL, 0UL, 2UL, 2UL, 6UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds subtensor succeeded\n" + << " Details:\n" + << " Result:\n" << sm << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c row() function with the Subquaternion class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c row() function with the Subquaternion specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testPageslice() +{ + using blaze::quatslice; + using blaze::pageslice; + using blaze::row; + + + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "Quatslice pageslice() function"; + + initialize(); + + { + RT quatslice1 = quatslice( quat_, 0UL ); + RT quatslice2 = quatslice( quat_, 0UL ); + auto pageslice1 = pageslice( quatslice1, 1UL ); + auto pageslice2 = pageslice( quatslice2, 1UL ); + + if( pageslice1 != pageslice2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Row function failed\n" + << " Details:\n" + << " Result:\n" << pageslice1 << "\n" + << " Expected result:\n" << pageslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + if( row(pageslice1,1) != row(pageslice2,1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << row(pageslice1,1) << "\n" + << " Expected result: " << row(pageslice2,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *pageslice1.begin(1) != *pageslice2.begin(1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *pageslice1.begin(1) << "\n" + << " Expected result: " << *pageslice2.begin(1) << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT quatslice1 = quatslice( quat_, 0UL ); + auto pageslice2 = pageslice( quatslice1, 2UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds row succeeded\n" + << " Details:\n" + << " Result:\n" << pageslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c row() function with the Subquaternion class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c row() function with the Subquaternion specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testRowslice() +{ + using blaze::quatslice; + using blaze::rowslice; + using blaze::row; + + + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "Quatslice rowslice() function"; + + initialize(); + + { + RT quatslice1 = quatslice( quat_, 0UL ); + RT quatslice2 = quatslice( quat_, 2UL ); + auto rowslice1 = rowslice( quatslice1, 1UL ); + auto rowslice2 = rowslice( quatslice2, 1UL ); + + if( rowslice1 != rowslice2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Row function failed\n" + << " Details:\n" + << " Result:\n" << rowslice1 << "\n" + << " Expected result:\n" << rowslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( row(rowslice1,1) != row(rowslice2,1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << row(rowslice1,1) << "\n" + << " Expected result: " << row(rowslice2,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *rowslice1.begin(1) != *rowslice2.begin(1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *rowslice1.begin(1) << "\n" + << " Expected result: " << *rowslice2.begin(1) << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT quatslice1 = quatslice( quat_, 0UL ); + auto rowslice6 = rowslice( quatslice1, 6UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds row succeeded\n" + << " Details:\n" + << " Result:\n" << rowslice6 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Test of the \c column() function with the Subquaternion class template. +// +// \return void +// \exception std::runtime_error Error detected. +// +// This function performs a test of the \c column() function with the Subquaternion specialization. +// In case an error is detected, a \a std::runtime_error exception is thrown. +*/ +void DenseGeneralTest::testColumnslice() +{ + using blaze::quatslice; + using blaze::columnslice; + using blaze::column; + + + //===================================================================================== + // quaternion tests + //===================================================================================== + + { + test_ = "Quatslice columnslice() function"; + + initialize(); + + { + RT quatslice1 = quatslice( quat_, 1UL ); + RT quatslice2 = quatslice( quat_, 1UL ); + auto columnslice1 = columnslice( quatslice1, 1UL ); + auto columnslice2 = columnslice( quatslice2, 1UL ); + + if( columnslice1 != columnslice2 ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Row function failed\n" + << " Details:\n" + << " Result:\n" << columnslice1 << "\n" + << " Expected result:\n" << columnslice2 << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( row(columnslice1,1) != row(columnslice2,1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Subscript operator access failed\n" + << " Details:\n" + << " Result: " << row(columnslice1,1) << "\n" + << " Expected result: " << row(columnslice2,1) << "\n"; + throw std::runtime_error( oss.str() ); + } + + if( *columnslice1.begin(1) != *columnslice2.begin(1) ) { + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Iterator access failed\n" + << " Details:\n" + << " Result: " << *columnslice1.begin(1) << "\n" + << " Expected result: " << *columnslice2.begin(1) << "\n"; + throw std::runtime_error( oss.str() ); + } + } + + try { + RT quatslice1 = quatslice( quat_, 0UL ); + auto columnslice6 = columnslice( quatslice1, 6UL ); + + std::ostringstream oss; + oss << " Test: " << test_ << "\n" + << " Error: Setup of out-of-bounds row succeeded\n" + << " Details:\n" + << " Result:\n" << columnslice6 << "\n"; + throw std::runtime_error( oss.str() ); + } + catch( std::invalid_argument& ) {} + } +} +//************************************************************************************************* //================================================================================================= From bf4bb54dfa4bf2075073a55a63b0f233f500363a Mon Sep 17 00:00:00 2001 From: Parsa Amini Date: Mon, 8 Jul 2019 10:14:20 -0500 Subject: [PATCH 11/14] Verbose CTest output --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index a51abc2..bd190e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -41,6 +41,8 @@ jobs: # Run all tests - run: name: Run all the tests + environment: + CTEST_OUTPUT_ON_FAILURE: TRUE command: cmake --build build --target test -- -j1 ################################################################################ From 2b5a46dcc6977507e43e168ac5f5e4beb1adbb27 Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Mon, 8 Jul 2019 13:09:14 -0500 Subject: [PATCH 12/14] Modifying the quatslice iterator --- blaze_tensor/math/views/quatslice/Dense.h | 15 +++++----- .../mathtest/quatslice/DenseGeneralTest.cpp | 29 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/blaze_tensor/math/views/quatslice/Dense.h b/blaze_tensor/math/views/quatslice/Dense.h index 32334f2..4d8195c 100644 --- a/blaze_tensor/math/views/quatslice/Dense.h +++ b/blaze_tensor/math/views/quatslice/Dense.h @@ -627,7 +627,7 @@ inline typename QuatSlice::ConstPointer template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::Iterator - QuatSlice::begin( size_t k, size_t i ) + QuatSlice::begin( size_t i, size_t k ) { return quaternion_.begin( i, quat(), k ); } @@ -647,7 +647,7 @@ inline typename QuatSlice::Iterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::begin( size_t k, size_t i ) const + QuatSlice::begin( size_t i, size_t k ) const { return quaternion_.cbegin( i, quat(), k ); } @@ -667,7 +667,7 @@ inline typename QuatSlice::ConstIterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::cbegin( size_t k, size_t i ) const + QuatSlice::cbegin( size_t i, size_t k ) const { return quaternion_.cbegin( i, quat(), k ); } @@ -687,7 +687,7 @@ inline typename QuatSlice::ConstIterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::Iterator - QuatSlice::end( size_t k, size_t i ) + QuatSlice::end( size_t i, size_t k ) { return quaternion_.end( i, quat(), k ); } @@ -707,7 +707,7 @@ inline typename QuatSlice::Iterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::end( size_t k, size_t i ) const + QuatSlice::end( size_t i, size_t k ) const { return quaternion_.cend( i, quat(), k ); } @@ -727,7 +727,7 @@ inline typename QuatSlice::ConstIterator template< typename AT // Type of the dense quaternion , size_t... CRAs > // Compile time quatslice arguments inline typename QuatSlice::ConstIterator - QuatSlice::cend( size_t k, size_t i ) const + QuatSlice::cend( size_t i, size_t k ) const { return quaternion_.cend( i, quat(), k ); } @@ -815,7 +815,8 @@ inline QuatSlice& for( const auto& colList : list ) { size_t i( 0UL ); for( const auto& rowList : colList ) { - std::fill( std::copy( rowList.begin(), rowList.end(), left.begin( k,i) ), left.end(k,i), ElementType() ); + std::fill( + std::copy( rowList.begin(), rowList.end(), left.begin( i, k ) ), left.end( i, k ), ElementType() ); ++i; } ++k; diff --git a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp index e197b49..520c777 100644 --- a/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp +++ b/blazetest/src/mathtest/quatslice/DenseGeneralTest.cpp @@ -602,7 +602,6 @@ void DenseGeneralTest::testAssignment() quatslice1 = t1; - checkPages ( quatslice1, 2UL ); checkRows ( quatslice1, 5UL ); checkColumns ( quatslice1, 4UL ); @@ -2754,9 +2753,9 @@ void DenseGeneralTest::testIterator() test_ = "Iterator/ConstIterator conversion"; RT quatslice2 = blaze::quatslice( quat_, 1UL ); - RT::ConstIterator it( begin( quatslice2, 1UL, 2UL ) ); + RT::ConstIterator it( begin( quatslice2, 2UL, 1UL ) ); - if( it == end( quatslice2, 1UL, 2UL ) || *it != -2 ) { + if( it == end( quatslice2, 2UL, 1UL ) || *it != -2 ) { std::ostringstream oss; oss << " Test: " << test_ << "\n" << " Error: Failed iterator conversion detected\n"; @@ -2769,7 +2768,7 @@ void DenseGeneralTest::testIterator() test_ = "Iterator subtraction (end-begin)"; RT quatslice1 = blaze::quatslice( quat_, 1UL ); - const ptrdiff_t number( end( quatslice1, 1UL, 2UL ) - begin( quatslice1, 1UL, 2UL ) ); + const ptrdiff_t number( end( quatslice1, 2UL, 1UL ) - begin( quatslice1, 2UL, 1UL ) ); if( number != 4L ) { std::ostringstream oss; @@ -2787,7 +2786,7 @@ void DenseGeneralTest::testIterator() test_ = "Iterator subtraction (begin-end)"; RT quatslice1 = blaze::quatslice( quat_, 1UL ); - const ptrdiff_t number( begin( quatslice1, 1UL, 2UL ) - end( quatslice1, 1UL, 2UL ) ); + const ptrdiff_t number( begin( quatslice1, 2UL, 1UL ) - end( quatslice1, 2UL, 1UL ) ); if( number != -4L ) { std::ostringstream oss; @@ -2805,7 +2804,7 @@ void DenseGeneralTest::testIterator() test_ = "ConstIterator subtraction (end-begin)"; RT quatslice2 = blaze::quatslice( quat_, 1UL ); - const ptrdiff_t number( cend( quatslice2, 1UL, 2UL ) - cbegin( quatslice2, 1UL, 2UL ) ); + const ptrdiff_t number( cend( quatslice2, 2UL, 1UL ) - cbegin( quatslice2, 2UL, 1UL ) ); if( number != 4L ) { std::ostringstream oss; @@ -2823,7 +2822,7 @@ void DenseGeneralTest::testIterator() test_ = "ConstIterator subtraction (begin-end)"; RT quatslice2 = blaze::quatslice( quat_, 1UL ); - const ptrdiff_t number( cbegin( quatslice2, 1UL, 2UL ) - cend( quatslice2, 1UL, 2UL ) ); + const ptrdiff_t number( cbegin( quatslice2, 2UL, 1UL ) - cend( quatslice2, 2UL, 1UL ) ); if( number != -4L ) { std::ostringstream oss; @@ -2841,8 +2840,8 @@ void DenseGeneralTest::testIterator() test_ = "read-only access via ConstIterator"; RT quatslice3 = blaze::quatslice( quat_, 0UL ); - RT::ConstIterator it ( cbegin( quatslice3, 0UL, 4UL ) ); - RT::ConstIterator end( cend( quatslice3, 0UL, 4UL ) ); + RT::ConstIterator it ( cbegin( quatslice3, 4UL, 0UL ) ); + RT::ConstIterator end( cend( quatslice3, 4UL, 0UL ) ); if( it == end || *it != 7 ) { std::ostringstream oss; @@ -2940,7 +2939,7 @@ void DenseGeneralTest::testIterator() RT quatslice2 = blaze::quatslice( quat_, 1UL ); int value = 6; - for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + for( RT::Iterator it=begin( quatslice2, 3UL, 0UL ); it!=end( quatslice2, 3UL, 0UL ); ++it ) { *it = value++; } @@ -2971,7 +2970,7 @@ void DenseGeneralTest::testIterator() RT quatslice2 = blaze::quatslice( quat_, 1UL ); int value = 2; - for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + for( RT::Iterator it=begin( quatslice2, 3UL, 0UL ); it!=end( quatslice2, 3UL, 0UL ); ++it ) { *it += value++; } @@ -3002,7 +3001,7 @@ void DenseGeneralTest::testIterator() RT quatslice2 = blaze::quatslice( quat_, 1UL ); int value = 2; - for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + for( RT::Iterator it=begin( quatslice2, 3UL, 0UL ); it!=end( quatslice2, 3UL, 0UL ); ++it ) { *it -= value++; } @@ -3033,7 +3032,7 @@ void DenseGeneralTest::testIterator() RT quatslice2 = blaze::quatslice( quat_, 1UL ); int value = 1; - for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + for( RT::Iterator it=begin( quatslice2, 3UL, 0UL ); it!=end( quatslice2, 3UL, 0UL ); ++it ) { *it *= value++; } @@ -3063,7 +3062,7 @@ void DenseGeneralTest::testIterator() RT quatslice2 = blaze::quatslice( quat_, 1UL ); - for( RT::Iterator it=begin( quatslice2, 0UL, 3UL ); it!=end( quatslice2, 0UL, 3UL ); ++it ) { + for( RT::Iterator it=begin( quatslice2, 3UL, 0UL ); it!=end( quatslice2, 3UL, 0UL ); ++it ) { *it /= 2; } @@ -4073,7 +4072,7 @@ void DenseGeneralTest::testSubtensor() } // sm.begin( page, row) - if( *sm.begin(0,1) != 0 ) { + if( *sm.begin(1,0) != 0 ) { std::ostringstream oss; oss << " Test: " << test_ << "\n" << " Error: Iterator access failed\n" From 121da615a6b4285517f88db90b379b1080a36314 Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Tue, 9 Jul 2019 11:54:47 -0500 Subject: [PATCH 13/14] Working towards running CustomArray tests --- CMakeLists.txt | 14 +- README.md | 7 + blaze_tensor/math/constraints/Array.h | 4 +- blaze_tensor/math/dense/CustomArray.h | 450 +++++++++++++++--- blaze_tensor/math/dense/DynamicArray.h | 2 +- blaze_tensor/math/smp/default/DenseArray.h | 4 +- blaze_tensor/math/smp/hpx/DenseArray.h | 3 +- blaze_tensor/util/ArrayForEach.h | 2 +- .../customarray/AlignedPaddedTest1.cpp | 20 +- 9 files changed, 417 insertions(+), 89 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f33a3c4..355b711 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,9 @@ project(BlazeTensor LANGUAGES CXX VERSION "${BLAZE_TENSOR_MAJOR_VERSION}.${BLAZE_TENSOR_MINOR_VERSION}") +option(BLAZETENSOR_WITH_TESTS "Build BlazeTensor tests" OFF) +option(BLAZETENSOR_USE_HPX_THREADS "Use HPX thread backend" OFF) + # set minimally required C++ Standard set(CMAKE_CXX_STANDARD 14) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -81,10 +84,18 @@ target_link_libraries(BlazeTensor INTERFACE blaze::blaze) # setup HPX, if needed get_target_property(blaze_parallelization_mode blaze::blaze INTERFACE_COMPILE_DEFINITIONS) -if(blaze_parallelization_mode AND "${blaze_parallelization_mode}" STREQUAL "BLAZE_USE_HPX_THREADS") +if( + (blaze_parallelization_mode AND "${blaze_parallelization_mode}" STREQUAL "BLAZE_USE_HPX_THREADS") + OR BLAZETENSOR_USE_HPX_THREADS) + find_package(HPX REQUIRED NO_CMAKE_PACKAGE_REGISTRY) target_include_directories(BlazeTensor INTERFACE ${HPX_INCLUDE_DIRS}) target_link_libraries(BlazeTensor INTERFACE ${HPX_LIBRARIES}) + + # Force using HPX + if(BLAZETENSOR_USE_HPX_THREADS) + add_compile_definitions(BLAZE_USE_HPX_THREADS) + endif() endif() include(CMakePackageConfigHelpers) @@ -130,7 +141,6 @@ install( ) # Optionally build tests (primarily for devs) -option(BLAZETENSOR_WITH_TESTS "Build BlazeTensor tests" OFF) if(BLAZETENSOR_WITH_TESTS) enable_testing() include(CTest) diff --git a/README.md b/README.md index 30d0603..f1a612d 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,10 @@ integration service tracks the current build status for the master branch: ### Datastructures +- `blaze::DynamicArray`: a resizable, row-major ND dense array data structure + of arbitrary types +- `blaze::CustomArray`: a non-owning ND dense array data structure usable + to refer to some other ND dense array - `blaze::DynamicTensor`: a resizable, row-major 3D dense array data structure of arbitrary types - `blaze::CustomTensor`: a non-owning 3D dense array data structure usable @@ -85,6 +89,9 @@ integration service tracks the current build status for the master branch: tensor-like data structure with three additional argumnts: 'pagedilation', 'rowdilation' and 'columndilation' (step-size between the pages, rows and the columns of the underlying tensor, respectively). +- `blaze::QuatSlice<...>`: a view representing a slice of 'thickness' one along + the page/row/column tensor of a 4D dense array + ### Operations - All element-wise arithmetic operations that are supported by the Blaze library: diff --git a/blaze_tensor/math/constraints/Array.h b/blaze_tensor/math/constraints/Array.h index ee9527d..cf73151 100644 --- a/blaze_tensor/math/constraints/Array.h +++ b/blaze_tensor/math/constraints/Array.h @@ -59,7 +59,7 @@ namespace blaze { // In case the given data type \a T is not a N-dimensional array type, a compilation error // is created. */ -#define BLAZE_CONSTRAINT_MUST_BE_ARRAY_TYPE(T) \ +#define BLAZE_CONSTRAINT_MUST_BE_ND_ARRAY_TYPE(T) \ static_assert( ::blaze::IsNdArray_v, "Non-array type detected" ) //************************************************************************************************* @@ -79,7 +79,7 @@ namespace blaze { // In case the given data type \a T is a N-dimensional array type, a compilation error // is created. */ -#define BLAZE_CONSTRAINT_MUST_NOT_BE_ARRAY_TYPE(T) \ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_ND_ARRAY_TYPE(T) \ static_assert( !::blaze::IsNdArray_v, "Array type detected" ) //************************************************************************************************* diff --git a/blaze_tensor/math/dense/CustomArray.h b/blaze_tensor/math/dense/CustomArray.h index 847602e..4373aa7 100644 --- a/blaze_tensor/math/dense/CustomArray.h +++ b/blaze_tensor/math/dense/CustomArray.h @@ -475,6 +475,21 @@ class CustomArray inline CustomArray& operator=( const Type& set ); inline CustomArray& operator=( nested_initializer_list< N, Type > list ); + template< typename Other, size_t N1, size_t Dummy = N, typename = EnableIf_t< Dummy == 1 > > + inline CustomArray& operator=( const Other (&array)[N1] ); + + template< typename Other, size_t M, size_t N1, size_t Dummy = N, typename = EnableIf_t< Dummy == 2 > > + inline CustomArray& operator=( const Other (&array)[M][N1] ); + + template< typename Other, size_t O, size_t M, size_t N1, size_t Dummy = N, typename = EnableIf_t< Dummy == 3 > > + inline CustomArray& operator=( const Other (&array)[O][M][N1] ); + + template< typename Other, size_t P, size_t O, size_t M, size_t N1, size_t Dummy = N, typename = EnableIf_t< Dummy == 4 > > + inline CustomArray& operator=( const Other (&array)[P][O][M][N1] ); + + template< typename Other, size_t Q, size_t P, size_t O, size_t M, size_t N1, size_t Dummy = N, typename = EnableIf_t< Dummy == 5 > > + inline CustomArray& operator=(const Other (&array)[Q][P][O][M][N1]); + inline CustomArray& operator=( const CustomArray& rhs ); inline CustomArray& operator=( CustomArray&& rhs ) noexcept; @@ -642,28 +657,28 @@ class CustomArray BLAZE_ALWAYS_INLINE void stream( const SIMDType& value, Dims... dims ) noexcept; template< typename MT > - inline auto assign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAssign_v >; + inline auto assign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedAssign_v >*/; - template< typename MT > - inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; + //template< typename MT > + //inline auto assign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAssign_v >; template< typename MT > - inline auto addAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedAddAssign_v >; + inline auto addAssign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedAddAssign_v >*/; - template< typename MT > - inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; + //template< typename MT > + //inline auto addAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedAddAssign_v >; template< typename MT > - inline auto subAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSubAssign_v >; + inline auto subAssign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedSubAssign_v >*/; - template< typename MT > - inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; + //template< typename MT > + //inline auto subAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSubAssign_v >; template< typename MT > - inline auto schurAssign( const DenseArray& rhs ) -> DisableIf_t< VectorizedSchurAssign_v >; + inline auto schurAssign( const DenseArray& rhs ) /*-> DisableIf_t< VectorizedSchurAssign_v >*/; - template< typename MT > - inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; + //template< typename MT > + //inline auto schurAssign( const DenseArray& rhs ) -> EnableIf_t< VectorizedSchurAssign_v >; //@} //********************************************************************************************** @@ -1699,6 +1714,301 @@ inline CustomArray& //************************************************************************************************* +//************************************************************************************************* +/*!\brief Array assignment to all tensor elements. +// +// \param array \f$ M \times N \f$ dimensional array for the assignment. +// \return Reference to the assigned tensor. +// \exception std::invalid_argument Invalid array size. +// +// This assignment operator offers the option to directly set all elements of the tensor: + + \code + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + const int array[9] = { 0, 0, 0, + 0, 0, 0, + 0, 0, 0 }; + const int init[3][3] = { { 1, 2, 3 }, + { 4, 5 }, + { 7, 8, 9 } }; + blaze::CustomTensor A( array, 3UL, 3UL ); + A = init; + \endcode + +// The tensor is assigned the values from the given array. Missing values are initialized with +// default values (as e.g. the value 6 in the example). Note that the size of the array must +// match the size of the custom tensor. Otherwise a \a std::invalid_argument exception is thrown. +// Also note that after the assignment \a array will have the same entries as \a init. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other // Data type of the initialization array + , size_t N1 // Number of columns of the initialization array + , size_t Dummy // Dummy variable equal to N + , typename Enable > +inline CustomArray& + CustomArray::operator=( const Other (&array)[N1] ) +{ + if( dims_[0] != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for (size_t j=0UL; j A( array, 3UL, 3UL ); + A = init; + \endcode + +// The tensor is assigned the values from the given array. Missing values are initialized with +// default values (as e.g. the value 6 in the example). Note that the size of the array must +// match the size of the custom tensor. Otherwise a \a std::invalid_argument exception is thrown. +// Also note that after the assignment \a array will have the same entries as \a init. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other // Data type of the initialization array + , size_t M // Number of rows of the initialization array + , size_t N1 // Number of columns of the initialization array + , size_t Dummy // Dummy variable equal to N + , typename Enable > +inline CustomArray& + CustomArray::operator=( const Other (&array)[M][N1] ) +{ + if( dims_[1] != M || dims_[0] != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for (size_t i=0UL; i A( array, 3UL, 3UL ); + A = init; + \endcode + +// The tensor is assigned the values from the given array. Missing values are initialized with +// default values (as e.g. the value 6 in the example). Note that the size of the array must +// match the size of the custom tensor. Otherwise a \a std::invalid_argument exception is thrown. +// Also note that after the assignment \a array will have the same entries as \a init. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other // Data type of the initialization array + , size_t O // Number of pages of the initialization array + , size_t M // Number of rows of the initialization array + , size_t N1 // Number of columns of the initialization array + , size_t Dummy // Dummy variable equal to N + , typename Enable > +inline CustomArray& + CustomArray::operator=( const Other (&array)[O][M][N1] ) +{ + if( dims_[1] != M || dims_[0] != N || dims_[2] != O ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for (size_t k=0UL; k A( array, 3UL, 3UL ); + A = init; + \endcode + +// The tensor is assigned the values from the given array. Missing values are initialized with +// default values (as e.g. the value 6 in the example). Note that the size of the array must +// match the size of the custom tensor. Otherwise a \a std::invalid_argument exception is thrown. +// Also note that after the assignment \a array will have the same entries as \a init. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other // Data type of the initialization array + , size_t P // Number of quats of the initialization array + , size_t O // Number of pages of the initialization array + , size_t M // Number of rows of the initialization array + , size_t N1 // Number of columns of the initialization array + , size_t Dummy // Dummy variable equal to N + , typename Enable > +inline CustomArray& + CustomArray::operator=( const Other (&array)[P][O][M][N1] ) +{ + if( dims_[3] != P || dims_[2] != O || dims_[1] != M || dims_[0] != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + for (size_t l = 0UL; l < P; ++l) { + for (size_t k = 0UL; k < O; ++k) { + for (size_t i = 0UL; i < M; ++i) { + for (size_t j = 0UL; j < N; ++j) { + v_[((l*O + k)*M + i)*nn_ + j] = array[l][k][i][j]; + } + } + } + } + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Array assignment to all tensor elements. +// +// \param array \f$ M \times N \f$ dimensional array for the assignment. +// \return Reference to the assigned tensor. +// \exception std::invalid_argument Invalid array size. +// +// This assignment operator offers the option to directly set all elements of the tensor: + + \code + using blaze::unaligned; + using blaze::unpadded; + using blaze::rowMajor; + + const int array[9] = { 0, 0, 0, + 0, 0, 0, + 0, 0, 0 }; + const int init[3][3] = { { 1, 2, 3 }, + { 4, 5 }, + { 7, 8, 9 } }; + blaze::CustomTensor A( array, 3UL, 3UL ); + A = init; + \endcode + +// The tensor is assigned the values from the given array. Missing values are initialized with +// default values (as e.g. the value 6 in the example). Note that the size of the array must +// match the size of the custom tensor. Otherwise a \a std::invalid_argument exception is thrown. +// Also note that after the assignment \a array will have the same entries as \a init. +*/ +template< size_t N // Dimensionality of the array + , typename Type // Data type of the tensor + , bool AF // Alignment flag + , bool PF // Padding flag + , typename RT > // Result type +template< typename Other // Data type of the initialization array + , size_t Q // Number of of the initialization array + , size_t P // Number of quats of the initialization array + , size_t O // Number of pages of the initialization array + , size_t M // Number of rows of the initialization array + , size_t N1 // Number of columns of the initialization array + , size_t Dummy // Dummy variable equal to N + , typename Enable > +inline CustomArray& + CustomArray::operator=( const Other (&array)[Q][P][O][M][N1] ) +{ + if( dims_[4] != Q || dims_[3] != P || dims_[2] != O || dims_[1] != M || dims_[0] != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + for (size_t m = 0UL; m < Q; ++m) { + for (size_t l = 0UL; l < P; ++l) { + for (size_t k = 0UL; k < O; ++k) { + for (size_t i = 0UL; i < M; ++i) { + for (size_t j = 0UL; j < N; ++j) { + v_[(((m*P + l)*O + k)*M + i)*nn_ + j] = array[m][l][k][i][j]; + } + } + } + } + } + return *this; +} +//************************************************************************************************* + + //************************************************************************************************* /*!\brief Copy assignment operator for CustomArray. // @@ -2788,7 +3098,7 @@ template< size_t N // Dimensionality of the array , typename RT > // Result type template< typename MT > // Type of the right-hand side dense array inline auto CustomArray::assign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedAssign_v > + /*-> DisableIf_t< VectorizedAssign_v >*/ { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); @@ -2814,19 +3124,19 @@ inline auto CustomArray::assign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // Dimensionality of the array - , typename Type // Data type of the array - , bool AF // Alignment flag - , bool PF // Padding flag - , typename RT > // Result type -template< typename MT > // Type of the right-hand side dense array -inline auto CustomArray::assign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); - +//template< size_t N // Dimensionality of the array +// , typename Type // Data type of the array +// , bool AF // Alignment flag +// , bool PF // Padding flag +// , typename RT > // Result type +//template< typename MT > // Type of the right-hand side dense array +//inline auto CustomArray::assign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +// // constexpr bool remainder( !PF || !IsPadded_v ); // // const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) ); @@ -2874,7 +3184,7 @@ inline auto CustomArray::assign( const DenseArray& rhs ) // } // } // } -} +//} //************************************************************************************************* @@ -2896,7 +3206,7 @@ template< size_t N // Dimensionality of the array , typename RT > // Result type template< typename MT > // Type of the right-hand side dense array inline auto CustomArray::addAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedAddAssign_v > + //-> DisableIf_t< VectorizedAddAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); @@ -2922,19 +3232,19 @@ inline auto CustomArray::addAssign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // Dimensionality of the array - , typename Type // Data type of the array - , bool AF // Alignment flag - , bool PF // Padding flag - , typename RT > // Result type -template< typename MT > // Type of the right-hand side dense array -inline auto CustomArray::addAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedAddAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); - +//template< size_t N // Dimensionality of the array +// , typename Type // Data type of the array +// , bool AF // Alignment flag +// , bool PF // Padding flag +// , typename RT > // Result type +//template< typename MT > // Type of the right-hand side dense array +//inline auto CustomArray::addAssign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedAddAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +// // constexpr bool remainder( !PF || !IsPadded_v ); // // for (size_t k=0UL; k::addAssign( const DenseArray& rhs ) // } // } // } -} +//} //************************************************************************************************* @@ -2987,7 +3297,7 @@ template< size_t N // Dimensionality of the array , typename RT > // Result type template< typename MT > // Type of the right-hand side dense array inline auto CustomArray::subAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedSubAssign_v > + //-> DisableIf_t< VectorizedSubAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); @@ -3013,18 +3323,18 @@ inline auto CustomArray::subAssign( const DenseArray& rhs ) // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // Dimensionality of the array - , typename Type // Data type of the array - , bool AF // Alignment flag - , bool PF // Padding flag - , typename RT > // Result type -template< typename MT > // Type of the right-hand side dense array -inline auto CustomArray::subAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedSubAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +//template< size_t N // Dimensionality of the array +// , typename Type // Data type of the array +// , bool AF // Alignment flag +// , bool PF // Padding flag +// , typename RT > // Result type +//template< typename MT > // Type of the right-hand side dense array +//inline auto CustomArray::subAssign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedSubAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); // constexpr bool remainder( !PF || !IsPadded_v ); // @@ -3056,7 +3366,7 @@ inline auto CustomArray::subAssign( const DenseArray& rhs ) // } // } // } -} +//} //************************************************************************************************* @@ -3078,7 +3388,7 @@ template< size_t N // Dimensionality of the array , typename RT > // Result type template< typename MT > // Type of the right-hand side dense array inline auto CustomArray::schurAssign( const DenseArray& rhs ) - -> DisableIf_t< VectorizedSchurAssign_v > + //-> DisableIf_t< VectorizedSchurAssign_v > { BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); @@ -3104,18 +3414,18 @@ inline auto CustomArray::schurAssign( const DenseArray& rhs // in erroneous results and/or in compilation errors. Instead of using this function use the // assignment operator. */ -template< size_t N // Dimensionality of the array - , typename Type // Data type of the array - , bool AF // Alignment flag - , bool PF // Padding flag - , typename RT > // Result type -template< typename MT > // Type of the right-hand side dense array -inline auto CustomArray::schurAssign( const DenseArray& rhs ) - -> EnableIf_t< VectorizedSchurAssign_v > -{ - BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); - - BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); +//template< size_t N // Dimensionality of the array +// , typename Type // Data type of the array +// , bool AF // Alignment flag +// , bool PF // Padding flag +// , typename RT > // Result type +//template< typename MT > // Type of the right-hand side dense array +//inline auto CustomArray::schurAssign( const DenseArray& rhs ) +// -> EnableIf_t< VectorizedSchurAssign_v > +//{ +// BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); +// +// BLAZE_INTERNAL_ASSERT( dims_ == (~rhs).dimensions() , "Invalid array access index" ); // constexpr bool remainder( !PF || !IsPadded_v ); // @@ -3143,7 +3453,7 @@ inline auto CustomArray::schurAssign( const DenseArray& rhs // } // } // } -} +//} //************************************************************************************************* diff --git a/blaze_tensor/math/dense/DynamicArray.h b/blaze_tensor/math/dense/DynamicArray.h index 17393f7..6bcae37 100644 --- a/blaze_tensor/math/dense/DynamicArray.h +++ b/blaze_tensor/math/dense/DynamicArray.h @@ -488,7 +488,7 @@ class DynamicArray //**Member variables**************************************************************************** /*!\name Member variables */ //@{ - std::array< size_t, N > dims_; //!< The current dimensions of the array (dims[1]...dims_[N]) . + std::array< size_t, N > dims_; //!< The current dimensions of the array (dims[0]...dims_[N-1]) . size_t nn_; //!< The alignment adjusted number of columns. size_t capacity_; //!< The maximum capacity of the array. Type* BLAZE_RESTRICT v_; //!< The dynamically allocated array elements. diff --git a/blaze_tensor/math/smp/default/DenseArray.h b/blaze_tensor/math/smp/default/DenseArray.h index 1dba1d5..ee14ba9 100644 --- a/blaze_tensor/math/smp/default/DenseArray.h +++ b/blaze_tensor/math/smp/default/DenseArray.h @@ -47,8 +47,8 @@ #include #include -#include -#include +#include +#include namespace blaze { diff --git a/blaze_tensor/math/smp/hpx/DenseArray.h b/blaze_tensor/math/smp/hpx/DenseArray.h index fb385fc..8bd7c73 100644 --- a/blaze_tensor/math/smp/hpx/DenseArray.h +++ b/blaze_tensor/math/smp/hpx/DenseArray.h @@ -4,7 +4,7 @@ // \brief Header file for the HPX-based dense array SMP implementation // // Copyright (C) 2012-2018 Klaus Iglberger - All Rights Reserved -// Copyright (C) 2018 Hartmut Kaiser - All Rights Reserved +// Copyright (C) 2018-2019 Hartmut Kaiser - All Rights Reserved // // This file is part of the Blaze library. You can redistribute it and/or modify it under // the terms of the New (Revised) BSD License. Redistribution and use in source and binary @@ -71,6 +71,7 @@ #include #include #include +#include // #include namespace blaze { diff --git a/blaze_tensor/util/ArrayForEach.h b/blaze_tensor/util/ArrayForEach.h index e5a5b2a..d17ad61 100644 --- a/blaze_tensor/util/ArrayForEach.h +++ b/blaze_tensor/util/ArrayForEach.h @@ -167,7 +167,7 @@ void ArrayForEachPadded( } } -template< size_t N, typename F > +template< typename F > void ArrayForEachPadded( std::array< size_t, 2 > const& dims, size_t nn, F const& f, size_t base = 0 ) { diff --git a/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp b/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp index 1611e18..2fdaa48 100644 --- a/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp +++ b/blazetest/src/mathtest/customarray/AlignedPaddedTest1.cpp @@ -75,10 +75,10 @@ namespace customarray { */ AlignedPaddedTest::AlignedPaddedTest() { - testConstructors(); + //testConstructors(); testAssignment(); - testAddAssign(); - testSubAssign(); + //testAddAssign(); + //testSubAssign(); } //************************************************************************************************* @@ -460,7 +460,7 @@ void AlignedPaddedTest::testAssignment() std::unique_ptr memory( blaze::allocate( 64UL ) ); MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); - mat = {{{1, 2, 3}, {4, 5, 6}}, {{1, 2, 3}, {4, 5, 6}}}; + mat = {{{1, 2, 3}, {4, 5, 6}}, {{-1, -2, -3}, {-4, -5, -6}}}; checkRows ( mat, 2UL ); checkColumns ( mat, 3UL ); @@ -472,10 +472,10 @@ void AlignedPaddedTest::testAssignment() checkNonZeros( mat, 0UL, 1UL, 3UL ); checkNonZeros( mat, 1UL, 1UL, 3UL ); - if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 3 || - mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || - mat(1,0,0) != 1 || mat(1,0,1) != 2 || mat(1,0,2) != 3 || - mat(1,1,0) != 4 || mat(1,1,1) != 5 || mat(1,1,2) != 6 ) { + if( mat(0,0,0) != 1 || mat(0,0,1) != 2 || mat(0,0,2) != 3 || + mat(0,1,0) != 4 || mat(0,1,1) != 5 || mat(0,1,2) != 6 || + mat(1,0,0) != -1 || mat(1,0,1) != -2 || mat(1,0,2) != -3 || + mat(1,1,0) != -4 || mat(1,1,1) != -5 || mat(1,1,2) != -6 ) { std::ostringstream oss; oss << " Test: " << test_ << "\n" << " Error: Assignment failed\n" @@ -525,10 +525,10 @@ void AlignedPaddedTest::testAssignment() { test_ = "Row-major CustomArray array assignment"; - const int array[2UL][2UL][3UL] = {{{1, 2, 3}, {4, 5, 6}}, {{1, 2, 3}, {4, 5, 6}}}; + const int arr[2UL][2UL][3UL] = {{{1, 2, 3}, {4, 5, 6}}, {{1, 2, 3}, {4, 5, 6}}}; std::unique_ptr memory( blaze::allocate( 64UL ) ); MT mat( memory.get(), 2UL, 2UL, 3UL, 16UL ); - mat = MT( &array[0][0][0], 2UL, 2UL, 3UL ); + mat = arr; checkRows ( mat, 2UL ); checkColumns ( mat, 3UL ); From 95c693e07666ba33802aa171737d25799f8eb8c7 Mon Sep 17 00:00:00 2001 From: Bita Hasheminezhad Date: Wed, 10 Jul 2019 15:33:25 -0500 Subject: [PATCH 14/14] modifying the generate function --- blaze_tensor/math/DynamicArray.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/blaze_tensor/math/DynamicArray.h b/blaze_tensor/math/DynamicArray.h index 424edc0..270d227 100644 --- a/blaze_tensor/math/DynamicArray.h +++ b/blaze_tensor/math/DynamicArray.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -79,10 +80,10 @@ class Rand< DynamicArray > //**Generate functions************************************************************************** /*!\name Generate functions */ //@{ - template< typename... Dims > + template< typename... Dims> inline const DynamicArray generate( Dims... dims ) const; - template< typename Arg, typename... Dims > + template< typename Arg, typename... Dims, size_t DummyN = N, typename = EnableIf_t< sizeof...(Dims) == DummyN > > inline const DynamicArray generate( const Arg& min, const Arg& max, Dims... dims ) const; //@} //********************************************************************************************** @@ -110,7 +111,7 @@ class Rand< DynamicArray > // \return The generated random array. */ template< size_t N // The dimensionality of the array - , typename Type > // Data type of the array + , typename Type> // Data type of the array template< typename... Dims > inline const DynamicArray Rand< DynamicArray >::generate( Dims... dims ) const @@ -135,7 +136,10 @@ inline const DynamicArray */ template< size_t N // The dimensionality of the array , typename Type > // Data type of the array -template< typename Arg, typename... Dims > // Min/max argument type +template< typename Arg // Min/max argument type + , typename... Dims + , size_t DummyN // Dummy variable equal to N + , typename Enable > inline const DynamicArray Rand< DynamicArray >::generate( const Arg& min, const Arg& max, Dims... dims ) const {