vmmlib  1.7.0
 All Classes Namespaces Functions Pages
qtucker3_tensor.hpp
1 /*
2  * Copyright (c) 2006-2014, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /* @author Susanne Suter
34  *
35  * Quantized version of Tucker3 tensor
36  * - 16bit linear factor matrices quantization
37  * - 8bit logarithmic core tensor quantization
38  *
39  * reference:
40  * - Suter, Iglesias, Marton, Agus, Elsener, Zollikofer, Gopi, Gobbetti, and Pajarola:
41  * "Interactive Multiscale Tensor Reconstruction for Multiresolution Volume Visualization",
42  * IEEE Transactions on Visualization and Computer Graphics. 2011.
43  *
44  */
45 
46 #ifndef __VMML__QTUCKER3_TENSOR__HPP__
47 #define __VMML__QTUCKER3_TENSOR__HPP__
48 
49 #define CORE_RANGE 127
50 
51 
52 #include <vmmlib/tucker3_tensor.hpp>
53 
54 
55 namespace vmml
56 {
57 
58  template< size_t R1, size_t R2, size_t R3, size_t I1, size_t I2, size_t I3, typename T_value = float, typename T_coeff = double >
60  {
61  public:
62  typedef float T_internal;
63 
65 
69 
74 
79 
81 
82  static const size_t SIZE = R1*R2*R3 + I1*R1 + I2*R2 + I3*R3;
83 
86  qtucker3_tensor( t3_core_type& core, u1_type& U1, u2_type& U2, u3_type& U3 );
87  qtucker3_tensor( const t3_type& data_, u1_type& U1, u2_type& U2, u3_type& U3 );
88  qtucker3_tensor( const tucker3_type& other );
89  ~qtucker3_tensor();
90 
91  void enable_quantify_hot() { _is_quantify_hot = true; _is_quantify_log = false; _is_quantify_linear = false;};
92  void disable_quantify_hot() { _is_quantify_hot = false; } ;
93  void enable_quantify_linear() { _is_quantify_linear = true; _is_quantify_hot = false;};
94  void disable_quantify_linear() { _is_quantify_linear = false; } ;
95  void enable_quantify_log() { _is_quantify_log = true; _is_quantify_hot = false;};
96  void disable_quantify_log() { _is_quantify_log = false; } ;
97 
98  void get_core_signs( t3_core_signs_type& signs_ ) { signs_ = _signs; };
99  void set_core_signs( const t3_core_signs_type signs_ ) { _signs = signs_; } ;
100 
101  T_internal get_hottest_value() { return _hottest_core_value; };
102  void set_hottest_value( const T_internal value_ ) { _hottest_core_value = value_; } ;
103 
104  void set_core( t3_core_type& core ) { _core = t3_core_type( core ); _core_comp.cast_from( core ); } ;
105  void set_u1( u1_type& U1 ) { *_u1 = U1; _u1_comp->cast_from( U1 ); } ;
106  void set_u2( u2_type& U2 ) { *_u2 = U2; _u2_comp->cast_from( U2 ); } ;
107  void set_u3( u3_type& U3 ) { *_u3 = U3; _u3_comp->cast_from( U3 ); } ;
108 
109  void get_core( t3_core_type& data_ ) const { data_ = _core; } ;
110  void get_u1( u1_type& U1 ) const { U1 = *_u1; } ;
111  void get_u2( u2_type& U2 ) const { U2 = *_u2; } ;
112  void get_u3( u3_type& U3 ) const { U3 = *_u3; } ;
113 
114  void set_core_comp( t3_core_comp_type& core ) { _core_comp = t3_core_comp_type( core ); _core.cast_from( _core_comp ); } ;
115  void set_u1_comp( u1_comp_type& U1 ) { *_u1_comp = U1; _u1->cast_from( U1 ); } ;
116  void set_u2_comp( u2_comp_type& U2 ) { *_u2_comp = U2; _u2->cast_from( U2 ); } ;
117  void set_u3_comp( u3_comp_type& U3 ) { *_u3_comp = U3; _u3->cast_from( U3 ); } ;
118 
119  void get_core_comp( t3_core_comp_type& data_ ) const { data_ = _core_comp; } ;
120  void get_u1_comp( u1_comp_type& U1 ) const { U1 = *_u1_comp; } ;
121  void get_u2_comp( u2_comp_type& U2 ) const { U2 = *_u2_comp; } ;
122  void get_u3_comp( u3_comp_type& U3 ) const { U3 = *_u3_comp; } ;
123 
124  //get number of nonzeros for tensor decomposition
125  size_t nnz() const;
126  size_t nnz( const T_value& threshold ) const;
127  size_t nnz_core() const;
128  size_t size_core() const;
129  size_t size() const { return SIZE; } ;
130 
131  void threshold_core( const size_t& nnz_core_, size_t& nnz_core_is_ );
132  void threshold_core( const T_coeff& threshold_value_, size_t& nnz_core_ );
133  void reconstruct( t3_type& data_,
134  const T_internal& u_min_, const T_internal& u_max_,
135  const T_internal& core_min_, const T_internal& core_max_ );
136  void reconstruct( t3_type& data_,
137  const T_internal& u1_min_, const T_internal& u1_max_,
138  const T_internal& u2_min_, const T_internal& u2_max_,
139  const T_internal& u3_min_, const T_internal& u3_max_,
140  const T_internal& core_min_, const T_internal& core_max_ );
141 
142  template< typename T_init>
143  void decompose( const t3_type& data_,
144  T_internal& u1_min_, T_internal& u1_max_,
145  T_internal& u2_min_, T_internal& u2_max_,
146  T_internal& u3_min_, T_internal& u3_max_,
147  T_internal& core_min_, T_internal& core_max_,
148  T_init init );
149  template< typename T_init>
150  void decompose( const t3_type& data_,
151  T_internal& u_min_, T_internal& u_max_,
152  T_internal& core_min_, T_internal& core_max_,
153  T_init init );
154 
155  template< typename T_init>
156  void tucker_als( const t3_type& data_, T_init init );
157 
158  friend std::ostream& operator << ( std::ostream& os, const tucker3_type& t3 )
159  {
160  t3_core_type core; t3.get_core( core );
161  u1_type* u1 = new u1_type; t3.get_u1( *u1 );
162  u2_type* u2 = new u2_type; t3.get_u2( *u2 );
163  u3_type* u3 = new u3_type; t3.get_u3( *u3 );
164 
165  os << "U1: " << std::endl << *u1 << std::endl
166  << "U2: " << std::endl << *u2 << std::endl
167  << "U3: " << std::endl << *u3 << std::endl
168  << "core: " << std::endl << core << std::endl;
169 
170  delete u1;
171  delete u2;
172  delete u3;
173  return os;
174  }
175 
176  void cast_members();
177  void cast_comp_members();
178  void quantize_basis_matrices( T_internal& u_min_, T_internal& u_max_ );
179  void quantize_basis_matrices( T_internal& u1_min_, T_internal& u1_max_, T_internal& u2_min_, T_internal& u2_max_, T_internal& u3_min_, T_internal& u3_max_ );
180  void quantize_core( T_internal& core_min_, T_internal& core_max_ );
181  void dequantize_basis_matrices( const T_internal& u1_min_, const T_internal& u1_max_, const T_internal& u2_min_, const T_internal& u2_max_, const T_internal& u3_min_, const T_internal& u3_max_ );
182  void dequantize_core( const T_internal& core_min_, const T_internal& core_max_ );
183 
184  protected:
185  tucker3_type operator=( const tucker3_type& ) { return (*this); };
186 
187  template< typename T_init>
188  void decompose( const t3_type& data_, T_init init );
189  void reconstruct( t3_type& data_ );
190 
191  private:
192  //t3_core_type* _core ;
193  u1_type* _u1 ;
194  u2_type* _u2 ;
195  u3_type* _u3 ;
196  t3_core_type _core ;
197 
198  //used only internally for computations to have a higher precision
199  t3_core_comp_type _core_comp ;
200  u1_comp_type* _u1_comp ;
201  u2_comp_type* _u2_comp ;
202  u3_comp_type* _u3_comp ;
203 
204  T_internal _hottest_core_value;
205  t3_core_signs_type _signs;
206 
207  bool _is_quantify_hot;
208  bool _is_quantify_log;
209  bool _is_quantify_linear;
210 
211  }; // class qtucker3_tensor
212 
213 
214 #define VMML_TEMPLATE_STRING template< size_t R1, size_t R2, size_t R3, size_t I1, size_t I2, size_t I3, typename T_value, typename T_coeff >
215 #define VMML_TEMPLATE_CLASSNAME qtucker3_tensor< R1, R2, R3, I1, I2, I3, T_value, T_coeff >
216 
217 
218 VMML_TEMPLATE_STRING
219 VMML_TEMPLATE_CLASSNAME::qtucker3_tensor( )
220  : _hottest_core_value( 0 )
221  , _is_quantify_hot( false )
222  , _is_quantify_log( false )
223  , _is_quantify_linear( false )
224 {
225  _core.zero();
226  _u1 = new u1_type(); _u1->zero();
227  _u2 = new u2_type(); _u2->zero();
228  _u3 = new u3_type(); _u3->zero();
229  _core_comp.zero();
230  _u1_comp = new u1_comp_type(); _u1_comp->zero();
231  _u2_comp = new u2_comp_type(); _u2_comp->zero();
232  _u3_comp = new u3_comp_type(); _u3_comp->zero();
233 
234  _signs.zero();
235 }
236 
237 VMML_TEMPLATE_STRING
238 VMML_TEMPLATE_CLASSNAME::qtucker3_tensor( t3_core_type& core )
239  : _hottest_core_value( 0 )
240  , _is_quantify_hot( false )
241  , _is_quantify_log( false )
242  , _is_quantify_linear( false )
243 {
244  _core = core;
245  _u1 = new u1_type(); _u1->zero();
246  _u2 = new u2_type(); _u2->zero();
247  _u3 = new u3_type(); _u3->zero();
248  _u1_comp = new u1_comp_type(); _u1_comp->zero();
249  _u2_comp = new u2_comp_type(); _u2_comp->zero();
250  _u3_comp = new u3_comp_type(); _u3_comp->zero();
251  _core_comp.cast_from( core );
252 
253  _signs.zero();
254 }
255 
256 VMML_TEMPLATE_STRING
257 VMML_TEMPLATE_CLASSNAME::qtucker3_tensor( t3_core_type& core, u1_type& U1, u2_type& U2, u3_type& U3 )
258  : _hottest_core_value( 0 )
259  , _is_quantify_hot( false )
260  , _is_quantify_log( false )
261  , _is_quantify_linear( false )
262 {
263  _core = core;
264  _u1 = new u1_type( U1 );
265  _u2 = new u2_type( U2 );
266  _u3 = new u3_type( U3 );
267  _u1_comp = new u1_comp_type();
268  _u2_comp = new u2_comp_type();
269  _u3_comp = new u3_comp_type();
270  cast_comp_members();
271 
272  _signs.zero();
273 }
274 
275 VMML_TEMPLATE_STRING
276 VMML_TEMPLATE_CLASSNAME::qtucker3_tensor( const t3_type& data_, u1_type& U1, u2_type& U2, u3_type& U3 )
277  : _hottest_core_value( 0 )
278  , _is_quantify_hot( false )
279  , _is_quantify_log( false )
280  , _is_quantify_linear( false )
281 {
282  _u1 = new u1_type( U1 );
283  _u2 = new u2_type( U2 );
284  _u3 = new u3_type( U3 );
285  _u1_comp = new u1_comp_type();
286  _u2_comp = new u2_comp_type();
287  _u3_comp = new u3_comp_type();
288 
289  t3_hooi< R1, R2, R3, I1, I2, I3, T_coeff >::derive_core( data_, *_u1, *_u2, *_u3, _core );
290 
291  cast_comp_members();
292 
293  _signs.zero();
294 }
295 
296 VMML_TEMPLATE_STRING
297 VMML_TEMPLATE_CLASSNAME::qtucker3_tensor( const tucker3_type& other )
298  : _hottest_core_value( 0 )
299  , _is_quantify_hot( false )
300  , _is_quantify_log( false )
301  , _is_quantify_linear( false )
302 {
303  _u1 = new u1_type();
304  _u2 = new u2_type();
305  _u3 = new u3_type();
306  _u1_comp = new u1_comp_type();
307  _u2_comp = new u2_comp_type();
308  _u3_comp = new u3_comp_type();
309 
310  other.get_core( _core );
311  other.get_u1( *_u1 );
312  other.get_u2( *_u2 );
313  other.get_u3( *_u3 );
314 
315  cast_comp_members();
316 
317  _signs.zero();
318 }
319 
320 
321 
322 VMML_TEMPLATE_STRING
323 void
324 VMML_TEMPLATE_CLASSNAME::cast_members()
325 {
326  _u1->cast_from( *_u1_comp );
327  _u2->cast_from( *_u2_comp );
328  _u3->cast_from( *_u3_comp );
329  _core.cast_from( _core_comp);
330 }
331 
332 VMML_TEMPLATE_STRING
333 void
334 VMML_TEMPLATE_CLASSNAME::cast_comp_members()
335 {
336  _u1_comp->cast_from( *_u1 );
337  _u2_comp->cast_from( *_u2 );
338  _u3_comp->cast_from( *_u3 );
339  _core_comp.cast_from( _core);
340 }
341 
342 
343 VMML_TEMPLATE_STRING
344 size_t
345 VMML_TEMPLATE_CLASSNAME::nnz_core() const
346 {
347  return _core_comp.nnz();
348 }
349 
350 VMML_TEMPLATE_STRING
351 size_t
352 VMML_TEMPLATE_CLASSNAME::size_core() const
353 {
354  return _core_comp.size();
355 }
356 
357 
358 
359 VMML_TEMPLATE_STRING
360 void
361 VMML_TEMPLATE_CLASSNAME::quantize_basis_matrices(T_internal& u1_min_, T_internal& u1_max_,
362  T_internal& u2_min_, T_internal& u2_max_,
363  T_internal& u3_min_, T_internal& u3_max_ )
364 {
365  _u1_comp->quantize( *_u1, u1_min_, u1_max_ );
366  _u2_comp->quantize( *_u2, u2_min_, u2_max_ );
367  _u3_comp->quantize( *_u3, u3_min_, u3_max_ );
368 }
369 
370 
371 VMML_TEMPLATE_STRING
372 void
373 VMML_TEMPLATE_CLASSNAME::quantize_basis_matrices(T_internal& u_min_, T_internal& u_max_)
374 {
375  u_min_ = _u1_comp->get_min();
376  T_internal u2_min = _u2_comp->get_min();
377  T_internal u3_min = _u3_comp->get_min();
378 
379  if ( u2_min < u_min_) {
380  u_min_ = u2_min;
381  }
382  if ( u3_min < u_min_) {
383  u_min_ = u3_min;
384  }
385 
386  u_max_ = _u1_comp->get_max();
387  T_internal u2_max = _u2_comp->get_max();
388  T_internal u3_max = _u3_comp->get_max();
389 
390  if ( u2_max > u_max_ ) {
391  u_max_ = u2_max;
392  }
393  if ( u3_max > u_max_ ) {
394  u_max_ = u3_max;
395  }
396 
397  _u1_comp->quantize_to( *_u1, u_min_, u_max_ );
398  _u2_comp->quantize_to( *_u2, u_min_, u_max_ );
399  _u3_comp->quantize_to( *_u3, u_min_, u_max_ );
400 
401 #if 0
402  std::cout << "quantized (1u): " << std::endl << "u1-u3: " << std::endl
403  << *_u1 << std::endl << *_u1_comp << std::endl
404  << *_u2 << std::endl << *_u2_comp << std::endl
405  << *_u3 << std::endl << *_u3_comp << std::endl
406  << " core " << std::endl
407  << _core << std::endl
408  << " core_comp " << std::endl
409  << _core_comp << std::endl;
410 #endif
411 }
412 
413 
414 VMML_TEMPLATE_STRING
415 void
416 VMML_TEMPLATE_CLASSNAME::quantize_core( T_internal& core_min_, T_internal& core_max_ )
417 {
418  if ( _is_quantify_hot ) {
419  _hottest_core_value = _core_comp.at(0,0,0);
420  _core_comp.at( 0, 0, 0 ) = 0;
421  _core_comp.quantize_log( _core, _signs, core_min_, core_max_, T_coeff(CORE_RANGE) );
422  } else if ( _is_quantify_linear ) {
423  _core_comp.quantize( _core, core_min_, core_max_ );
424  } else if ( _is_quantify_log ) {
425  _core_comp.quantize_log( _core, _signs, core_min_, core_max_, T_coeff(CORE_RANGE) );
426  } else {
427  _core_comp.quantize( _core, core_min_, core_max_ );
428  std::cout << "quant.method not specified" << std::endl;
429  }
430 }
431 
432 
433 VMML_TEMPLATE_STRING
434 void
435 VMML_TEMPLATE_CLASSNAME::dequantize_basis_matrices( const T_internal& u1_min_, const T_internal& u1_max_,
436  const T_internal& u2_min_, const T_internal& u2_max_,
437  const T_internal& u3_min_, const T_internal& u3_max_ )
438 {
439  _u1->dequantize( *_u1_comp, u1_min_, u1_max_ );
440  _u2->dequantize( *_u2_comp, u2_min_, u2_max_ );
441  _u3->dequantize( *_u3_comp, u3_min_, u3_max_ );
442 }
443 
444 VMML_TEMPLATE_STRING
445 void
446 VMML_TEMPLATE_CLASSNAME::dequantize_core( const T_internal& core_min_, const T_internal& core_max_ )
447 {
448  if ( _is_quantify_hot ) {
449  _core.dequantize_log( _core_comp, _signs, core_min_, core_max_ );
450  _core.at(0,0,0) = _hottest_core_value;
451  _core_comp.at(0,0,0) = _hottest_core_value;
452  } else if ( _is_quantify_linear ) {
453  _core.dequantize( _core_comp, core_min_, core_max_ );
454  } else if ( _is_quantify_log ) {
455  _core.dequantize_log( _core_comp, _signs, core_min_, core_max_ );
456  } else {
457  _core.dequantize( _core_comp, core_min_, core_max_ );
458  }
459 }
460 
461 VMML_TEMPLATE_STRING
462 VMML_TEMPLATE_CLASSNAME::~qtucker3_tensor( )
463 {
464  delete _u1;
465  delete _u2;
466  delete _u3;
467  delete _u1_comp;
468  delete _u2_comp;
469  delete _u3_comp;
470 }
471 
472 VMML_TEMPLATE_STRING
473 void
474 VMML_TEMPLATE_CLASSNAME::reconstruct( t3_type& data_,
475  const T_internal& u_min_, const T_internal& u_max_,
476  const T_internal& core_min_, const T_internal& core_max_ )
477 {
478  dequantize_basis_matrices( u_min_, u_max_, u_min_, u_max_, u_min_, u_max_ );
479  dequantize_core( core_min_, core_max_ );
480 
481 #if 0
482  std::cout << "dequantized (1u): " << std::endl << "u1-u3: " << std::endl
483  << *_u1 << std::endl << *_u1_comp << std::endl
484  << *_u2 << std::endl << *_u2_comp << std::endl
485  << *_u3 << std::endl << *_u3_comp << std::endl
486  << " core " << std::endl
487  << _core << std::endl
488  << " core_comp " << std::endl
489  << _core_comp << std::endl;
490 #endif
491 
492  reconstruct( data_ );
493 }
494 
495 VMML_TEMPLATE_STRING
496 void
497 VMML_TEMPLATE_CLASSNAME::reconstruct( t3_type& data_,
498  const T_internal& u1_min_, const T_internal& u1_max_,
499  const T_internal& u2_min_, const T_internal& u2_max_,
500  const T_internal& u3_min_, const T_internal& u3_max_,
501  const T_internal& core_min_, const T_internal& core_max_ )
502 {
503  dequantize_basis_matrices( u1_min_, u1_max_, u2_min_, u2_max_, u3_min_, u3_max_ );
504  dequantize_core( core_min_, core_max_ );
505 
506  reconstruct( data_ );
507 }
508 
509 VMML_TEMPLATE_STRING
510 void
511 VMML_TEMPLATE_CLASSNAME::reconstruct( t3_type& data_ )
512 {
513  t3_comp_type data;
514  data.cast_from( data_ );
515  t3_ttm::full_tensor3_matrix_multiplication( _core_comp, *_u1_comp, *_u2_comp, *_u3_comp, data );
516 
517  //convert reconstructed data, which is in type T_internal (double, float) to T_value (uint8 or uint16)
518  if( (sizeof(T_value) == 1) || (sizeof(T_value) == 2) ){
519  data_.float_t_to_uint_t( data );
520  } else {
521  data_.cast_from( data );
522  }
523 }
524 
525 
526 VMML_TEMPLATE_STRING
527 template< typename T_init>
528 void
529 VMML_TEMPLATE_CLASSNAME::decompose( const t3_type& data_, T_init init )
530 
531 {
532  tucker_als( data_, init );
533 }
534 
535 VMML_TEMPLATE_STRING
536 template< typename T_init>
537 void
538 VMML_TEMPLATE_CLASSNAME::decompose( const t3_type& data_,
539  T_internal& u1_min_, T_internal& u1_max_,
540  T_internal& u2_min_, T_internal& u2_max_,
541  T_internal& u3_min_, T_internal& u3_max_,
542  T_internal& core_min_, T_internal& core_max_,
543  T_init init )
544 
545 {
546  decompose( data_, init );
547 
548  quantize_basis_matrices( u1_min_, u1_max_, u2_min_, u2_max_, u3_min_, u3_max_ );
549  quantize_core(core_min_, core_max_ );
550 }
551 
552 VMML_TEMPLATE_STRING
553 template< typename T_init>
554 void
555 VMML_TEMPLATE_CLASSNAME::decompose( const t3_type& data_,
556  T_internal& u_min_, T_internal& u_max_,
557  T_internal& core_min_, T_internal& core_max_,
558  T_init init )
559 
560 {
561  decompose( data_, init );
562 
563  quantize_basis_matrices( u_min_, u_max_ );
564  quantize_core(core_min_, core_max_ );
565 }
566 
567 
568 VMML_TEMPLATE_STRING
569 template< typename T_init >
570 void
571 VMML_TEMPLATE_CLASSNAME::tucker_als( const t3_type& data_, T_init init )
572 {
573  t3_comp_type data;
574  data.cast_from( data_ );
575 
576  typedef t3_hooi< R1, R2, R3, I1, I2, I3, T_internal > hooi_type;
577  hooi_type::als( data, *_u1_comp, *_u2_comp, *_u3_comp, _core_comp, init );
578 
579  cast_members();
580 }
581 
582 
583 
584 VMML_TEMPLATE_STRING
585 size_t
586 VMML_TEMPLATE_CLASSNAME::nnz() const
587 {
588  size_t counter = 0;
589 
590  counter += _u1_comp->nnz();
591  counter += _u2_comp->nnz();
592  counter += _u3_comp->nnz();
593  counter += _core_comp.nnz();
594 
595  return counter;
596 }
597 
598 VMML_TEMPLATE_STRING
599 size_t
600 VMML_TEMPLATE_CLASSNAME::nnz( const T_value& threshold ) const
601 {
602  size_t counter = 0;
603 
604  counter += _u1_comp->nnz( threshold );
605  counter += _u2_comp->nnz( threshold );
606  counter += _u3_comp->nnz( threshold );
607  counter += _core_comp.nnz( threshold );
608 
609  return counter;
610 }
611 
612 
613 #undef VMML_TEMPLATE_STRING
614 #undef VMML_TEMPLATE_CLASSNAME
615 
616 } // namespace vmml
617 
618 #endif