41 #ifndef __VMML__TENSOR4__HPP__ 
   42 #define __VMML__TENSOR4__HPP__ 
   45 #include <vmmlib/enable_if.hpp> 
   46 #include "tensor3.hpp" 
   56     template< 
size_t I1, 
size_t I2, 
size_t I3, 
size_t I4, 
typename T = 
float >
 
   78         inline void get_tensor3( 
const size_t i4_, 
tensor3_t& t3_data_ ) 
const;
 
   80         inline tensor3_t& get_tensor3( 
size_t i4_ );
 
   81         inline const tensor3_t& get_tensor3( 
size_t i4_ ) 
const;
 
   82         inline void set_tensor3( 
size_t i4_, 
const tensor3_t& t3_data_ );
 
   84         static const size_t ROWS           = I1;
 
   85         static const size_t COLS           = I2;
 
   86         static const size_t SLICES         = I3;
 
   87         static const size_t T3S            = I4;
 
   88         static const size_t MATRIX_SIZE    = I1 * I2;
 
   89         static const size_t T3_SIZE        = I1 * I2 * I3;
 
   90         static const size_t SIZE           = I1 * I2 * I3 * I4;
 
   92         static size_t get_array_size_in_bytes();
 
   96         void clear_array_pointer();
 
   99         inline T& operator()( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 );
 
  100         inline const T& operator()( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 ) 
const;
 
  102         inline T& at( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 );
 
  103         inline const T& at( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 ) 
const;
 
  109         explicit tensor4(
void* memory) ;
 
  113         template< 
typename U >
 
  116         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4 >
 
  124         void operator=( T fill_value );
 
  125         void fill( T fill_value ); 
 
  130         void fill_random( 
int seed = -1 );
 
  131         void fill_random_signed( 
int seed = -1 );
 
  132         void fill_increasing_values( );
 
  134         const tensor4& operator=( 
const tensor4& source_ );
 
  139         template< 
typename input_iterator_t >
 
  140         void set( input_iterator_t begin_, input_iterator_t end_,
 
  141                  bool row_major_layout = 
true );
 
  146         T get_abs_min() 
const;
 
  147         T get_abs_max() 
const;
 
  151         size_t nnz( 
const T& threshold_ ) 
const;
 
  152         void threshold( 
const T& threshold_value_ );
 
  155         double frobenius_norm() 
const;
 
  157         double avg_frobenius_norm() 
const;
 
  161         void mean( T& mean_ ) 
const;
 
  163         double variance() 
const;
 
  164         double stdev() 
const;
 
  166         template< 
typename TT >
 
  169         template< 
size_t J1, 
size_t J2, 
size_t  J3, 
size_t J4, 
typename TT >
 
  173         template< 
typename TT >
 
  177         bool operator==( 
const tensor4& other ) 
const;
 
  178         bool operator!=( 
const tensor4& other ) 
const;
 
  182         bool equals( 
const tensor4& other, T tolerance ) 
const;
 
  185         template< 
typename compare_t >
 
  186         bool equals( 
const tensor4& other, compare_t& cmp ) 
const;
 
  189         inline tensor4 operator+( T scalar ) 
const;
 
  190         inline tensor4 operator-( T scalar ) 
const;
 
  192         void operator+=( T scalar );
 
  193         void operator-=( T scalar );
 
  195         inline tensor4 operator+( 
const tensor4& other ) 
const;
 
  196         inline tensor4 operator-( 
const tensor4& other ) 
const;
 
  198         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4 >
 
  202         void operator+=( 
const tensor4& other );
 
  203         void operator-=( 
const tensor4& other );
 
  208         tensor4 operator*( T scalar );
 
  209         void operator*=( T scalar );
 
  211         tensor4 operator/( T scalar );
 
  212         void operator/=( T scalar );
 
  218         friend std::ostream& operator << ( std::ostream& os,
 
  224             for(
size_t i4 = 0; i4 < I4; ++i4)
 
  226                 for(
size_t i3 = 0; i3 < I3; ++i3)
 
  228                     for(
size_t i1 = 0; i1 < I1; ++i1)
 
  232                         for(
size_t i2 = 0; i2 < I2; ++i2)
 
  236                                 os << T(t4.at( i1, i2, i3, i4 )) ;
 
  238                                 os << T(t4.at( i1, i2, i3, i4 )) << 
", " ;
 
  242                         os << 
")" << std::endl;
 
  245                         os << 
" *** " << std::endl;
 
  249                     os << 
"---- " << std::endl;
 
  255         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4 >
 
  257         get_sub_tensor4(
tensor4<J1, J2, J3, J4, T >& result, 
size_t row_offset, 
size_t col_offset, 
size_t slice_offset, 
size_t t3_offset) 
const;
 
  260         static void     tensor4_allocate_data( T*& array_ );
 
  261         static void     tensor4_deallocate_data( T*& array_ );
 
  266         const T*    get_array_ptr() 
const;
 
  274         inline size_t compute_index( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 ) 
const;
 
  276         template< 
typename TT >
 
  277         void quantize_log(
tensor4< I1, I2, I3, I4, TT >& quantized_, 
tensor4< I1, I2, I3, I4, char >& signs_, T& min_value_, T& max_value_, 
const TT& tt_range_) 
const;
 
  280         tensor3_t&                   _get_tensor3( 
size_t index_ );
 
  281         const tensor3_t&             _get_tensor3( 
size_t index_ ) 
const;
 
  287 #define VMML_TEMPLATE_STRING    template< size_t I1, size_t I2, size_t I3, size_t I4, typename T > 
  288 #define VMML_TEMPLATE_CLASSNAME tensor4< I1, I2, I3, I4, T > 
  295         VMML_TEMPLATE_CLASSNAME::tensor4( 
void* memory )
 
  296         : _array( reinterpret_cast<T*>( memory ) )
 
  303         VMML_TEMPLATE_CLASSNAME::tensor4()
 
  306             tensor4_allocate_data( _array );
 
  310         VMML_TEMPLATE_CLASSNAME::~tensor4()
 
  312             tensor4_deallocate_data( _array );
 
  316         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4 >
 
  317         typename enable_if< J1 <= I1 && J2 <= I2 && J3 <= I3 && J4 <= I4 >::type*
 
  318         VMML_TEMPLATE_CLASSNAME::
 
  319         get_sub_tensor4(tensor4<J1, J2, J3, J4, T >& result,
 
  320             size_t row_offset, 
size_t col_offset, 
size_t slice_offset, 
size_t t3_offset)
 const {
 
  321             #ifdef VMMLIB_SAFE_ACCESSORS 
  322             if (J1 + row_offset > I1 || J2 + col_offset > I2 || J3 + slice_offset > I3 || J4 + t3_offset > I4)
 
  323                 VMMLIB_ERROR(
"index out of bounds.", VMMLIB_HERE);
 
  326             for (
size_t t3 = 0; t3 < J4; ++t3) {
 
  327                 for (
size_t slice = 0; slice < J3; ++slice) {
 
  328                     for (
size_t row = 0; row < J1; ++row) {
 
  329                         for (
size_t col = 0; col < J2; ++col) {
 
  330                             result.at(row, col, slice, t3)
 
  331                                     = at(row_offset + row, col_offset + col, slice_offset + slice, t3_offset + t3);
 
  341         VMML_TEMPLATE_CLASSNAME::
 
  342         tensor4_allocate_data( T*& array_ )
 
  344             array_ = 
new T[ I1 * I2 * I3 * I4];
 
  349         VMML_TEMPLATE_CLASSNAME::
 
  350         tensor4_deallocate_data( T*& array_ )
 
  362         VMML_TEMPLATE_CLASSNAME::get_array_ptr()
 
  371         VMML_TEMPLATE_CLASSNAME::get_array_ptr()
 const 
  377         VMML_TEMPLATE_CLASSNAME::tensor4( 
const tensor4& source_ )
 
  379             tensor4_allocate_data( _array );
 
  385         template< 
typename U >
 
  386         VMML_TEMPLATE_CLASSNAME::tensor4( 
const tensor4< I1, I2, I3, I4, U >& source_ )
 
  388             const U* s_array = source_.get_array_ptr();
 
  389             tensor4_allocate_data( _array );
 
  390             for (
size_t index = 0; index < SIZE; ++index)
 
  392                 _array[ index ] = 
static_cast< T 
>( s_array[ index ] );
 
  397         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4 >
 
  398         VMML_TEMPLATE_CLASSNAME::tensor4( 
const tensor4< J1, J2, J3, J4, T >& source_ )
 
  400             tensor4_allocate_data( _array );
 
  401             size_t min1 = J1 < I1 ? J1 : I1;
 
  402             size_t min2 = J2 < I2 ? J2 : I2;
 
  403             size_t min3 = J3 < I3 ? J3 : I3;
 
  404             size_t min4 = J4 < I4 ? J4 : I4;
 
  408             for(
size_t i4 = 0; i4 < min4; ++i4 )
 
  410                 for(
size_t i3 = 0; i3 < min3; ++i3)
 
  412                     for(
size_t i2 = 0; i2 < min2; ++i2)
 
  414                         for(
size_t i1 = 0; i1 < min1; ++i1)
 
  416                             at(i1, i2, i3, i4) = source_(i1, i2, i3, i4);
 
  425         template< 
typename input_iterator_t >
 
  427         VMML_TEMPLATE_CLASSNAME::set(input_iterator_t begin_, input_iterator_t end_, 
bool row_major_layout) {
 
  428             input_iterator_t it(begin_);
 
  429             if (row_major_layout) {
 
  430                 for (
size_t i4 = 0; i4 < I4; ++i4) {
 
  431                     for (
size_t i3 = 0; i3 < I3; ++i3) {
 
  432                         for (
size_t i1 = 0; i1 < I1; ++i1) {
 
  433                             for (
size_t i2 = 0; i2 < I2; ++i2, ++it) {
 
  436                                 at(i1, i2, i3, i4) = 
static_cast<T
> (*it);
 
  442                 VMMLIB_ERROR( 
"Tensor4: set() not implemented for non-row major", VMMLIB_HERE );
 
  450         VMML_TEMPLATE_CLASSNAME::equals(
const tensor4< I1, I2, I3, I4, T >& other, T tolerance)
 const {
 
  452             if (T3S != other.T3S) {
 
  455             for (
size_t i4 = 0; is_ok && i4 < I4; ++i4) {
 
  456                 is_ok = _get_tensor3(i4).equals(other._get_tensor3(i4), tolerance);
 
  463         VMML_TEMPLATE_CLASSNAME::size()
 const 
  470         VMML_TEMPLATE_CLASSNAME::operator==( 
const tensor4< I1, I2, I3, I4, T >& other )
 const 
  472             const T* other_array = other.get_array_ptr();
 
  473             for(
size_t index = 0; index < SIZE; ++index)
 
  475                 if(_array[ index ] != other_array[ index] )
 
  487         VMML_TEMPLATE_CLASSNAME::operator!=( 
const tensor4< I1, I2, I3, I4, T >& other )
 const 
  489             return ! operator==( other );
 
  494         typename VMML_TEMPLATE_CLASSNAME::tensor3_t&
 
  495         VMML_TEMPLATE_CLASSNAME::
 
  496         _get_tensor3( 
size_t index_ )
 
  498             tensor3<I1, I2, I3, T>* tens3 = 
new tensor3<I1, I2, I3, T>( (
void *)(_array + I1 * I2 * I3 * index_));
 
  504         const typename VMML_TEMPLATE_CLASSNAME::tensor3_t&
 
  505         VMML_TEMPLATE_CLASSNAME::
 
  506         _get_tensor3( 
size_t index_ )
 const 
  508             const tensor3<I1, I2, I3, T>* tens3 = 
new tensor3<I1, I2, I3, T>( (
void *)(_array + I1 * I2 * I3 * index_));
 
  516         VMML_TEMPLATE_CLASSNAME::
 
  517         get_tensor3( 
const size_t i4_, tensor3_t& t3_data_ )
 const 
  519 #ifdef VMMLIB_SAFE_ACCESSORS 
  521                 VMMLIB_ERROR( 
"get_tensor3() - index out of bounds.", VMMLIB_HERE );
 
  524             t3_data_ = _get_tensor3( i4_ );
 
  530         inline typename VMML_TEMPLATE_CLASSNAME::tensor3_t&
 
  531         VMML_TEMPLATE_CLASSNAME::
 
  532         get_tensor3( 
size_t i4_ )
 
  534 #ifdef VMMLIB_SAFE_ACCESSORS 
  536                 VMMLIB_ERROR( 
"get_tensor3() - index out of bounds.", VMMLIB_HERE );
 
  538             return _get_tensor3( i4_ );
 
  543         inline const typename VMML_TEMPLATE_CLASSNAME::tensor3_t&
 
  544         VMML_TEMPLATE_CLASSNAME::
 
  545         get_tensor3( 
size_t i4_ )
 const 
  547 #ifdef VMMLIB_SAFE_ACCESSORS 
  549                 VMMLIB_ERROR( 
"get_tensor3() - index out of bounds.", VMMLIB_HERE );
 
  551             return _get_tensor3( i4_ );
 
  558         VMML_TEMPLATE_CLASSNAME::
 
  559         set_tensor3( 
size_t i4_, 
const tensor3_t& t3_data_ )
 
  561 #ifdef VMMLIB_SAFE_ACCESSORS 
  563                 VMMLIB_ERROR( 
"set_tensor3() - index out of bounds.", VMMLIB_HERE );
 
  565             memcpy(_array + I1*I2*I3*i4_, t3_data_.get_array_ptr(), I1*I2*I3*
sizeof(T));
 
  572         void VMML_TEMPLATE_CLASSNAME::fill( T fillValue )
 
  574             for( 
size_t i4 = 0; i4 < I4; ++i4 )
 
  576                 for( 
size_t i3 = 0; i3 < I3; ++i3 )
 
  578                     for( 
size_t i1 = 0; i1 < I1; ++i1 )
 
  580                         for( 
size_t i2 = 0; i2 < I2; ++i2 )
 
  582                             at(i1, i2, i3, i4) = fillValue;
 
  595         VMML_TEMPLATE_CLASSNAME::at( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 )
 
  597 #ifdef VMMLIB_SAFE_ACCESSORS 
  598             if ( i1 >= I1 || i2 >= I2 || i3 >= I3 || i4 >= I4 )
 
  599                 VMMLIB_ERROR( 
"at( i1, i2, i3, i4 ) - index out of bounds", VMMLIB_HERE );
 
  601             return _array[ i4 * T3_SIZE + i3 * MATRIX_SIZE + i2 * ROWS + i1 ];
 
  609         VMML_TEMPLATE_CLASSNAME::at( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 )
 const 
  611 #ifdef VMMLIB_SAFE_ACCESSORS 
  612             if ( i1 >= I1 || i2 >= I2 || i3 >= I3 || i4 >= I4 )
 
  613                 VMMLIB_ERROR( 
"at( i1, i2, i3, i4 ) - index out of bounds", VMMLIB_HERE );
 
  615             return _array[ i4 * T3_SIZE + i3 * MATRIX_SIZE + i2 * ROWS + i1 ];
 
  622         VMML_TEMPLATE_CLASSNAME::operator()( 
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 )
 
  624             return at( i1, i2, i3, i4 );
 
  631         VMML_TEMPLATE_CLASSNAME::operator()(  
size_t i1, 
size_t i2, 
size_t i3, 
size_t i4 )
 const 
  633             return at( i1, i2, i3, i4 );
 
  648         VMML_TEMPLATE_CLASSNAME::operator=( T fill_value )
 
  655         VMML_TEMPLATE_CLASSNAME::zero()
 
  657             fill( static_cast< T >( 0.0 ) );
 
  662         VMML_TEMPLATE_CLASSNAME::fill_increasing_values()
 
  664             double fillValue = 0.0f;
 
  665             for (
size_t i4 = 0; i4 < I4; ++i4) {
 
  666                 for (
size_t i3 = 0; i3 < I3; ++i3) {
 
  667                     for (
size_t i1 = 0; i1 < I1; ++i1) {
 
  668                         for (
size_t i2 = 0; i2 < I2; ++i2) {
 
  669                             at(i1, i2, i3, i4) = 
static_cast<T
> (fillValue);
 
  679         VMML_TEMPLATE_CLASSNAME::fill_random(
int seed)
 
  684             double fillValue = 0.0f;
 
  685             for( 
size_t index = 0; index < SIZE; ++index )
 
  688                 fillValue /= RAND_MAX;
 
  689                 fillValue *= (std::numeric_limits< T >::max)();
 
  690                 _array[ index ] = 
static_cast< T 
>( fillValue )  ;
 
  696         VMML_TEMPLATE_CLASSNAME::fill_random_signed(
int seed)
 
  701             double fillValue = 0.0f;
 
  702             for( 
size_t index = 0; index < SIZE; ++index )
 
  706                 fillValue /= RAND_MAX;
 
  707                 fillValue *= (std::numeric_limits< T >::max)();
 
  708                 T fillValue2 = 
static_cast< T 
>(fillValue) % (std::numeric_limits< T >::max)();
 
  709                 fillValue2 -= (std::numeric_limits< T >::max)()/2;
 
  710                 _array[ index ] = fillValue2  ;
 
  717         const VMML_TEMPLATE_CLASSNAME&
 
  718         VMML_TEMPLATE_CLASSNAME::operator=( 
const VMML_TEMPLATE_CLASSNAME& source_ )
 
  722                 memcpy( _array, source_._array, I1 * I2 * I3 * I4 * 
sizeof( T ) );
 
  728         template< 
typename TT >
 
  730         VMML_TEMPLATE_CLASSNAME::cast_from( 
const tensor4< I1, I2, I3, I4, TT >& other )
 
  732 #pragma omp parallel for 
  733             for(
long tensor_idx = 0; tensor_idx < (long)I4; ++tensor_idx)
 
  735 #pragma omp parallel for 
  736                 for( 
long slice_idx = 0; slice_idx < (long)I3; ++slice_idx )
 
  738 #pragma omp parallel for 
  739                     for( 
long row_index = 0; row_index < (long)I1; ++row_index )
 
  741 #pragma omp parallel for 
  742                         for( 
long col_index = 0; col_index < (long)I2; ++col_index )
 
  744                             at( row_index, col_index, slice_idx, tensor_idx ) =  
static_cast< T 
>(other.at( row_index, col_index, slice_idx, tensor_idx ));
 
  753         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4, 
typename TT >
 
  755         VMML_TEMPLATE_CLASSNAME::cast_from( 
const tensor4< J1, J2, J3, J4, TT >& other )
 
  758             int j4 = I4 < J4? I4 : J4;
 
  759             int j3 = I3 < J3? I3 : J3;
 
  760             int j2 = I2 < J2? I2 : J2;
 
  761             int j1 = I1 < J1? I1 : J1;
 
  762 #pragma omp parallel for 
  763             for(
long tensor_idx = 0; tensor_idx < (long)j4; ++tensor_idx)
 
  765 #pragma omp parallel for 
  766                 for( 
long slice_idx = 0; slice_idx < (long)j3; ++slice_idx )
 
  768 #pragma omp parallel for 
  769                     for( 
long row_index = 0; row_index < (long)j1; ++row_index )
 
  771 #pragma omp parallel for 
  772                         for( 
long col_index = 0; col_index < (long)j2; ++col_index )
 
  774                             at( row_index, col_index, slice_idx, tensor_idx ) =  
static_cast< T 
>(other.at( row_index, col_index, slice_idx, tensor_idx ));
 
  783         template< 
typename TT >
 
  785         VMML_TEMPLATE_CLASSNAME::float_t_to_uint_t( 
const tensor4< I1, I2, I3, I4, TT >& other )
 
  787             if( 
sizeof(T) == 1 || 
sizeof(T) == 2) {
 
  788                 const TT* otherdata = other.get_array_ptr();
 
  789                 for( 
size_t index = 0;index < SIZE; ++index )
 
  791                     _array[index] = T( (std::min)( (std::max)(
int(0), 
int( otherdata[index] + 0.5)), 
int((std::numeric_limits< T >::max)()) ));
 
  795                 this->cast_from( other );
 
  801         inline VMML_TEMPLATE_CLASSNAME
 
  802         VMML_TEMPLATE_CLASSNAME::operator+( T scalar )
 const 
  811         inline VMML_TEMPLATE_CLASSNAME
 
  812         VMML_TEMPLATE_CLASSNAME::operator-( T scalar )
 const 
  822         VMML_TEMPLATE_CLASSNAME::operator+=( T scalar )
 
  824             for(
size_t index = 0; index < SIZE; ++index)
 
  826                 _array[index] += scalar;
 
  833         VMML_TEMPLATE_CLASSNAME::operator-=( T scalar )
 
  835             for(
size_t index = 0; index < SIZE; ++index)
 
  837                 _array[index] -= scalar;
 
  843         inline VMML_TEMPLATE_CLASSNAME
 
  844         VMML_TEMPLATE_CLASSNAME::operator+( 
const tensor4& other )
 const 
  853         inline VMML_TEMPLATE_CLASSNAME
 
  854         VMML_TEMPLATE_CLASSNAME::operator-( 
const tensor4& other )
 const 
  863         VMML_TEMPLATE_CLASSNAME::operator+=( 
const tensor4& other )
 
  865             const T* dataptr = other.get_array_ptr();
 
  866             for(
size_t index = 0; index < SIZE; ++index)
 
  868                 _array[index] += dataptr[index];
 
  874         VMML_TEMPLATE_CLASSNAME::operator-=( 
const tensor4& other )
 
  876             const T* dataptr = other.get_array_ptr();
 
  877             for(
size_t index = 0; index < SIZE; ++index)
 
  879                 _array[index] -= dataptr[index];
 
  884         template< 
size_t J1, 
size_t J2, 
size_t J3, 
size_t J4 >
 
  885         typename enable_if< J1 < I1 && J2 < I2 && J3 < I3 && J4 < I4 >::type*
 
  886         VMML_TEMPLATE_CLASSNAME::operator+=( 
const tensor4< J1, J2, J3, J4, T>& other )
 
  888             for(
size_t i4 = 0; i4 < J4; ++i4)
 
  890                 for( 
size_t i3 = 0; i3 < J3; ++i3 )
 
  892                     for( 
size_t i1 = 0; i1 < J1; ++i1 )
 
  894                         for( 
size_t i2 = 0; i2 < J2; ++i2 )
 
  896                             at( i1, i2, i3, i4 ) += other.at(i1, i2, i3, i4);
 
  910         VMML_TEMPLATE_CLASSNAME
 
  911         VMML_TEMPLATE_CLASSNAME::operator*( T scalar )
 
  920         VMML_TEMPLATE_CLASSNAME::operator*=( T scalar )
 
  922             for(
size_t index = 0; index < SIZE; ++index)
 
  924                 _array[index] *= scalar;
 
  929         VMML_TEMPLATE_CLASSNAME
 
  930         VMML_TEMPLATE_CLASSNAME::operator/( T scalar )
 
  939         VMML_TEMPLATE_CLASSNAME::operator/=( T scalar )
 
  941             for(
size_t index = 0; index < SIZE; ++index)
 
  943                 _array[index] /= scalar;
 
  949         inline VMML_TEMPLATE_CLASSNAME
 
  950         VMML_TEMPLATE_CLASSNAME::operator-()
 const 
  956         VMML_TEMPLATE_CLASSNAME
 
  957         VMML_TEMPLATE_CLASSNAME::negate()
 const 
  960             T* dataptr = result.get_array_ptr();
 
  962             for(
size_t index = 0; index < SIZE; ++index)
 
  964                 dataptr[index] = _array[index] * -1;
 
  971         typename VMML_TEMPLATE_CLASSNAME::tensor3_t&
 
  972         VMML_TEMPLATE_CLASSNAME::average_I4(tensor3_t& t3)
 const 
  975             for(
size_t i3 = 0; i3 < I3; ++i3)
 
  977                 for( 
size_t i1 = 0; i1 < I1; ++i1 )
 
  979                     for( 
size_t i2 = 0; i2 < I2; ++i2 )
 
  982                         for( 
size_t i4 = 0; i4 < I4; ++i4 )
 
  984                             sum += at(i1,i2,i3,i4);
 
  986                         t3.at(i1,i2,i3) = sum/I4;
 
  996         VMML_TEMPLATE_CLASSNAME::get_array_size_in_bytes()
 
  998             return (
sizeof(T) * SIZE);
 
 1005         VMML_TEMPLATE_STRING
 
 1007         VMML_TEMPLATE_CLASSNAME::clear_array_pointer()
 
 1080         VMML_TEMPLATE_STRING
 
 1082         VMML_TEMPLATE_CLASSNAME::mode1_unfolding_fwd(mode1_unfolding_type& unfolding)
 const {
 
 1083             typedef matrix< I1, I2, T > slice_type;
 
 1084             slice_type* slice = 
new slice_type();
 
 1085             for (
size_t l = 0; l < I4; ++l) {
 
 1088                 for (
size_t k = 0; k < I3; ++k) {
 
 1089                     t3.get_frontal_slice_fwd(k, *slice);
 
 1090                     for (
size_t j = 0; j < I2; ++j) {
 
 1091                         unfolding.set_column(l*I2*I3 + k*I2 + j, slice->get_column(j));
 
 1098         VMML_TEMPLATE_STRING
 
 1100         VMML_TEMPLATE_CLASSNAME::mode2_unfolding_fwd(mode2_unfolding_type& unfolding)
 const {
 
 1101             typedef matrix< I2, I3, T > slice_type;
 
 1102             slice_type* slice = 
new slice_type();
 
 1103             for (
size_t i = 0; i < I1; ++i) {
 
 1104                 for (
size_t l = 0; l < I4; ++l) {
 
 1107                     t3.get_horizontal_slice_fwd(i, *slice);
 
 1108                     for (
size_t k = 0; k < I3; ++k) {
 
 1109                         unfolding.set_column(i*I3*I4 + l*I3 + k, slice->get_column(k));
 
 1116         VMML_TEMPLATE_STRING
 
 1118         VMML_TEMPLATE_CLASSNAME::mode3_unfolding_fwd(mode3_unfolding_type& unfolding)
 const {
 
 1119             typedef matrix< I2, I3, T > slice_type;
 
 1120             slice_type* slice = 
new slice_type();
 
 1121             for (
size_t j = 0; j < I2; ++j) {
 
 1122                 for (
size_t i = 0; i < I1; ++i) {
 
 1123                     for (
size_t l = 0; l < I4; ++l) {
 
 1126                         t3.get_horizontal_slice_fwd(i, *slice);
 
 1127                         unfolding.set_column(j*I4*I1 + i*I4 + l, slice->get_row(j));
 
 1134         VMML_TEMPLATE_STRING
 
 1136         VMML_TEMPLATE_CLASSNAME::mode4_unfolding_fwd(mode4_unfolding_type& unfolding)
 const {
 
 1137             for (
size_t k = 0; k < I3; ++k) {
 
 1138                 for (
size_t j = 0; j < I2; ++j) {
 
 1139                     for (
size_t i = 0; i < I1; ++i) {
 
 1140                         for (
size_t l = 0; l < I4; ++l) {
 
 1141                             unfolding.at(l,k*I1*I2 + j*I1 + i) = at(i,j,k,l);
 
 1148         VMML_TEMPLATE_STRING
 
 1150         VMML_TEMPLATE_CLASSNAME::frobenius_norm()
 const {
 
 1151             double f_norm = 0.0;
 
 1152             for (
long i3 = 0; i3 < long(I3); ++i3) {
 
 1153                 for (
long i4 = 0; i4 < long(I4); ++i4) {
 
 1154                     for (
long i1 = 0; i1 < long(I1); ++i1) {
 
 1156                         for (i2 = 0; i2 < long(I2); ++i2) {
 
 1157                             f_norm += at(i1, i2, i3, i4) * at(i1, i2, i3, i4);
 
 1162             return sqrt(f_norm);
 
 1165         VMML_TEMPLATE_STRING
 
 1167         VMML_TEMPLATE_CLASSNAME::frobenius_norm(
const tensor4< I1, I2, I3, I4, T>& other_)
 const {
 
 1168             double f_norm = 0.0;
 
 1170             T *it = _array, *it_end = _array + I1*I2*I3*I4;
 
 1171             T *it_other = other_._array;
 
 1172             for (; it != it_end; ++it, ++it_other) {
 
 1173                 abs_diff = fabs(*it - *it_other);
 
 1174                 f_norm += abs_diff * abs_diff;
 
 1177             return sqrt(f_norm);
 
 1180         VMML_TEMPLATE_STRING
 
 1181         template< 
typename TT >
 
 1183         VMML_TEMPLATE_CLASSNAME::quantize_log(tensor4< I1, I2, I3, I4, TT >& quantized_, tensor4< I1, I2, I3, I4, char >& signs_, T& min_value_, T& max_value_, 
const TT& tt_range_)
 const {
 
 1184             double max_tt_range = double(tt_range_);
 
 1185             double min_tt_range = 0;
 
 1188             max_value_ = get_abs_max();
 
 1189             double t_range = max_value_ - min_value_;
 
 1192             TT* it_quant = quantized_.get_array_ptr();
 
 1193             char* it_sign = signs_.get_array_ptr();
 
 1194             for (; it != _array+I1*I2*I3*I4; ++it, ++it_quant, ++it_sign) {
 
 1195                 T value = fabs(*it);
 
 1196                 *it_sign = ((*it) < 0.f) ? 0 : 1;
 
 1198                 if (std::numeric_limits<TT>::is_signed) {
 
 1199                     quant_value = log2(1 + value) / log2(1 + t_range) * tt_range_;
 
 1200                     *it_quant = TT((std::min)((std::max)(min_tt_range, 
double(quant_value + 0.5)), max_tt_range));
 
 1202                     quant_value = log2(1 + (value - min_value_)) / log2(1 + t_range) * tt_range_;
 
 1203                     *it_quant = TT((std::min)((std::max)(min_tt_range, 
double(quant_value + 0.5)), max_tt_range));
 
 1208         VMML_TEMPLATE_STRING
 
 1210         VMML_TEMPLATE_CLASSNAME::mean()
 const {
 
 1212             T* it = _array, *it_end = _array + I1*I2*I3*I4;
 
 1213             for (; it != it_end; ++it) {
 
 1214                 val += double(abs(*it));
 
 1217             return ( val / size());
 
 1220         VMML_TEMPLATE_STRING
 
 1222         VMML_TEMPLATE_CLASSNAME::mean(T& mean_)
 const {
 
 1223             mean_ = 
static_cast<T
> (mean());
 
 1226         VMML_TEMPLATE_STRING
 
 1228         VMML_TEMPLATE_CLASSNAME::variance()
 const {
 
 1230             double sum_val = 0.0;
 
 1231             double mean_val = mean();
 
 1232             T* it = _array, *it_end = _array+I1*I2*I3*I4;
 
 1233             for (; it != it_end; ++it) {
 
 1234                 val = double(*it) - mean_val;
 
 1239             return double(sum_val / (size() - 1));
 
 1242         VMML_TEMPLATE_STRING
 
 1244         VMML_TEMPLATE_CLASSNAME::stdev()
 const {
 
 1245             return sqrt(variance());
 
 1248         VMML_TEMPLATE_STRING
 
 1250         VMML_TEMPLATE_CLASSNAME::get_min()
 const {
 
 1251             T tensor4_min = 
static_cast<T
> ((std::numeric_limits<T>::max)());
 
 1253             T *it = _array, *it_end = _array + I1*I2*I3*I4;
 
 1254             for (; it != it_end; ++it) {
 
 1255                 if (*it < tensor4_min) {
 
 1262         VMML_TEMPLATE_STRING
 
 1264         VMML_TEMPLATE_CLASSNAME::get_max()
 const {
 
 1265             T tensor4_max = 
static_cast<T
> (0);
 
 1267             T *it = _array, *it_end = _array + I1*I2*I3*I4;
 
 1268             for (; it != it_end; ++it) {
 
 1269                 if (*it > tensor4_max) {
 
 1276         VMML_TEMPLATE_STRING
 
 1278         VMML_TEMPLATE_CLASSNAME::get_abs_min()
 const {
 
 1279             T tensor4_min = 
static_cast<T
> ((std::numeric_limits<T>::max)());
 
 1281             T *it = _array, *it_end = _array + I1*I2*I3*I4;
 
 1282             for (; it != it_end; ++it) {
 
 1283                 if (fabs(*it) < fabs(tensor4_min)) {
 
 1284                     tensor4_min = fabs(*it);
 
 1290         VMML_TEMPLATE_STRING
 
 1292         VMML_TEMPLATE_CLASSNAME::get_abs_max()
 const {
 
 1293             T tensor4_max = 
static_cast<T
> (0);
 
 1295             T *it = _array, *it_end = _array + I1*I2*I3*I4;
 
 1296             for (; it != it_end; ++it) {
 
 1297                 if (fabs(*it) > fabs(tensor4_max)) {
 
 1298                     tensor4_max = fabs(*it);
 
 1304 #undef VMML_TEMPLATE_STRING 
 1305 #undef VMML_TEMPLATE_CLASSNAME