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