aGrUM  0.16.0
IDatabaseTable_tpl.h
Go to the documentation of this file.
1 
29 
30 #ifndef DOXYGEN_SHOULD_SKIP_THIS
31 
32 namespace gum {
33 
34  namespace learning {
35 
36  // ===========================================================================
37  // Unsafe handlers
38  // ===========================================================================
39 
40  // default constructor
41  template < typename T_DATA, template < typename > class ALLOC >
43  const IDatabaseTable< T_DATA, ALLOC >& db) :
44  DBHandler< T_DATA, ALLOC >(),
45  __db(&db), __row(&(db.content())),
46  __end_index(std::size_t(__row->size())) {
47  GUM_CONSTRUCTOR(IDatabaseTable::Handler);
48  }
49 
50 
51  // copy constructor
52  template < typename T_DATA, template < typename > class ALLOC >
53  INLINE IDatabaseTable< T_DATA, ALLOC >::Handler::Handler(
54  const typename IDatabaseTable< T_DATA, ALLOC >::Handler& h) :
55  DBHandler< T_DATA, ALLOC >(),
56  __db(h.__db), __row(h.__row), __index(h.__index),
57  __begin_index(h.__begin_index), __end_index(h.__end_index) {
58  GUM_CONS_CPY(IDatabaseTable::Handler);
59  }
60 
61 
62  // move constructor
63  template < typename T_DATA, template < typename > class ALLOC >
64  INLINE IDatabaseTable< T_DATA, ALLOC >::Handler::Handler(
65  typename IDatabaseTable< T_DATA, ALLOC >::Handler&& h) :
66  DBHandler< T_DATA, ALLOC >(),
67  __db(h.__db), __row(h.__row), __index(h.__index),
68  __begin_index(h.__begin_index), __end_index(h.__end_index) {
69  GUM_CONS_MOV(IDatabaseTable::Handler);
70  }
71 
72 
73  // destructor
74  template < typename T_DATA, template < typename > class ALLOC >
75  INLINE IDatabaseTable< T_DATA, ALLOC >::Handler::~Handler() {
76  GUM_DESTRUCTOR(IDatabaseTable::Handler);
77  }
78 
79 
80  // copy operator
81  template < typename T_DATA, template < typename > class ALLOC >
82  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler&
83  IDatabaseTable< T_DATA, ALLOC >::Handler::
84  operator=(const typename IDatabaseTable< T_DATA, ALLOC >::Handler& h) {
85  __db = h.__db;
86  __row = h.__row;
87  __index = h.__index;
88  __begin_index = h.__begin_index;
89  __end_index = h.__end_index;
90  return *this;
91  }
92 
93 
94  // move operator
95  template < typename T_DATA, template < typename > class ALLOC >
96  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler&
97  IDatabaseTable< T_DATA, ALLOC >::Handler::
98  operator=(typename IDatabaseTable< T_DATA, ALLOC >::Handler&& h) {
99  __db = h.__db;
100  __row = h.__row;
101  __index = h.__index;
102  __begin_index = h.__begin_index;
103  __end_index = h.__end_index;
104  return *this;
105  }
106 
107 
108  // returns the current row pointed to by the handler
109  template < typename T_DATA, template < typename > class ALLOC >
110  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler::const_reference
112  return __row->operator[](__index);
113  }
114 
115 
116  // Dereferences the value pointed to by the handler (unsafe version)
117  template < typename T_DATA, template < typename > class ALLOC >
118  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler::const_pointer
119  IDatabaseTable< T_DATA, ALLOC >::Handler::operator->() const {
120  return &(__row->operator[](__index));
121  }
122 
123 
124  // makes the handler point to the next row
125  template < typename T_DATA, template < typename > class ALLOC >
126  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler&
127  IDatabaseTable< T_DATA, ALLOC >::Handler::operator++() {
128  ++__index;
129  return *this;
130  }
131 
132 
133  // makes the handler point to the previous row
134  template < typename T_DATA, template < typename > class ALLOC >
135  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler&
136  IDatabaseTable< T_DATA, ALLOC >::Handler::operator--() {
137  if (__index > __begin_index) --__index;
138  return *this;
139  }
140 
141 
142  // moves the handler by i rows
143  template < typename T_DATA, template < typename > class ALLOC >
144  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler&
145  IDatabaseTable< T_DATA, ALLOC >::Handler::operator+=(const std::size_t i) {
146  __index += i;
147  return *this;
148  }
149 
150 
151  // moves back the handler by i rows
152  template < typename T_DATA, template < typename > class ALLOC >
153  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler&
154  IDatabaseTable< T_DATA, ALLOC >::Handler::operator-=(const std::size_t i) {
155  if (__index >= __begin_index + i)
156  __index -= i;
157  else
158  __index = __begin_index;
159  return *this;
160  }
161 
162 
163  // checks whether two handlers point on the same row
164  template < typename T_DATA, template < typename > class ALLOC >
166  operator==(const Handler& handler) const {
167  return __index == handler.__index;
168  }
169 
170 
171  // checks whether two handlers point to different rows
172  template < typename T_DATA, template < typename > class ALLOC >
174  operator!=(const Handler& handler) const {
175  return __index != handler.__index;
176  }
177 
178 
179  // returns the number of rows managed by the handler
180  template < typename T_DATA, template < typename > class ALLOC >
181  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::Handler::size() const {
182  return __end_index - __begin_index;
183  }
184 
185 
186  // return the number of rows of the whole database
187  template < typename T_DATA, template < typename > class ALLOC >
188  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::Handler::DBSize() const {
189  if (__row != nullptr)
190  return __row->size();
191  else
192  return std::size_t(0);
193  }
194 
195 
196  // returns the current row pointed to by the handler
197  template < typename T_DATA, template < typename > class ALLOC >
198  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler::const_reference
199  IDatabaseTable< T_DATA, ALLOC >::Handler::rowSafe() const {
200  if (__index >= __end_index) {
201  GUM_ERROR(OutOfBounds, "the handler has reached its end");
202  }
203 
204  return __row->operator[](__index);
205  }
206 
207 
208  // returns the current row pointed to by the handler
209  template < typename T_DATA, template < typename > class ALLOC >
210  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler::reference
211  IDatabaseTable< T_DATA, ALLOC >::Handler::rowSafe() {
212  if (__index >= __end_index) {
213  GUM_ERROR(OutOfBounds, "the handler has reached its end");
214  }
215 
216  return const_cast< Matrix< T_DATA >* >(__row)->operator[](__index);
217  }
218 
219 
220  // returns the current row pointed to by the handler (unsafe version)
221  template < typename T_DATA, template < typename > class ALLOC >
222  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler::const_reference
223  IDatabaseTable< T_DATA, ALLOC >::Handler::row() const {
224  return __row->operator[](__index);
225  }
226 
227 
228  // returns the current row pointed to by the handler (unsafe version)
229  template < typename T_DATA, template < typename > class ALLOC >
230  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler::reference
231  IDatabaseTable< T_DATA, ALLOC >::Handler::row() {
232  return const_cast< Matrix< T_DATA >* >(__row)->operator[](__index);
233  }
234 
235 
236  // makes the handler point to the next row
237  template < typename T_DATA, template < typename > class ALLOC >
238  INLINE void IDatabaseTable< T_DATA, ALLOC >::Handler::nextRow() {
239  ++__index;
240  }
241 
242 
243  // returns the number of the current row
244  template < typename T_DATA, template < typename > class ALLOC >
245  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::Handler::numRow() const {
246  return (__index >= __begin_index) ? __index - __begin_index : 0;
247  }
248 
249  // indicates whether the handler has reached its end or not
250  template < typename T_DATA, template < typename > class ALLOC >
251  INLINE bool IDatabaseTable< T_DATA, ALLOC >::Handler::hasRows() const {
252  return (__index < __end_index);
253  }
254 
255  // puts the handler to the beginning of the database area it handles
256  template < typename T_DATA, template < typename > class ALLOC >
257  INLINE void IDatabaseTable< T_DATA, ALLOC >::Handler::reset() {
258  __index = __begin_index;
259  }
260 
261 
262  // returns a new handler that points to the beginning of the
263  // database area of the current handler */
264  template < typename T_DATA, template < typename > class ALLOC >
265  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler
266  IDatabaseTable< T_DATA, ALLOC >::Handler::begin() const {
267  Handler handler(*this);
268  handler.reset();
269  return handler;
270  }
271 
272 
273  // returns a new handler that points to the end of the
274  // database area of the current handler */
275  template < typename T_DATA, template < typename > class ALLOC >
276  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler
277  IDatabaseTable< T_DATA, ALLOC >::Handler::end() const {
278  Handler handler(*this);
279  handler.__index = __end_index;
280  return handler;
281  }
282 
283 
284  // sets the area in the database the handler will handle
285  template < typename T_DATA, template < typename > class ALLOC >
286  INLINE void
287  IDatabaseTable< T_DATA, ALLOC >::Handler::setRange(std::size_t begin,
288  std::size_t end) {
289  if (begin > end) std::swap(begin, end);
290 
291  // check that the end belongs to the database, else raise an exception
292  if (__row == nullptr) {
293  GUM_ERROR(NullElement, "the handler does not point to any database");
294  }
295  if (end > __row->size()) {
296  GUM_ERROR(SizeError,
297  "the database has fewer rows ("
298  << __row->size() << ") than the upper range (" << end
299  << ") specified to the handler");
300  }
301 
302  __begin_index = begin;
303  __end_index = end;
304  __index = begin;
305  }
306 
307 
308  // returns the current range of the handler
309  template < typename T_DATA, template < typename > class ALLOC >
310  INLINE std::pair< std::size_t, std::size_t >
311  IDatabaseTable< T_DATA, ALLOC >::Handler::range() const {
312  return std::pair< std::size_t, std::size_t >(__begin_index, __end_index);
313  }
314 
315 
316  // returns the names of the variables
317  template < typename T_DATA, template < typename > class ALLOC >
318  INLINE const typename IDatabaseTable< T_DATA, ALLOC >::Handler::
319  template DBVector< std::string >&
320  IDatabaseTable< T_DATA, ALLOC >::Handler::variableNames() const {
321  return __db->variableNames();
322  }
323 
324 
325  // returns the number of variables (columns) of the database
326  template < typename T_DATA, template < typename > class ALLOC >
327  INLINE std::size_t
328  IDatabaseTable< T_DATA, ALLOC >::Handler::nbVariables() const {
329  if (__db != nullptr)
330  return __db->variableNames().size();
331  else
332  return 0;
333  }
334 
335 
336  // returns a pointer on the database
337  template < typename T_DATA, template < typename > class ALLOC >
338  INLINE const IDatabaseTable< T_DATA, ALLOC >&
339  IDatabaseTable< T_DATA, ALLOC >::Handler::database() const {
340  if (__db == nullptr) {
341  GUM_ERROR(NullElement,
342  "The database handler does not point toward a database");
343  }
344  return *__db;
345  }
346 
347 
348  // ===========================================================================
349  // Safe handlers
350  // ===========================================================================
351 
352  // attach a new handler to the database
353  template < typename T_DATA, template < typename > class ALLOC >
354  INLINE void IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::__attachHandler() {
355  if (this->__db != nullptr) { this->__db->__attachHandler(this); }
356  }
357 
358 
359  // detach a handler
360  template < typename T_DATA, template < typename > class ALLOC >
361  INLINE void IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::__detachHandler() {
362  if (this->__db != nullptr) { this->__db->__detachHandler(this); }
363  }
364 
365 
366  // default constructor
367  template < typename T_DATA, template < typename > class ALLOC >
368  INLINE IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::HandlerSafe(
369  const IDatabaseTable< T_DATA, ALLOC >& db) :
370  IDatabaseTable< T_DATA, ALLOC >::Handler(db) {
371  __attachHandler();
372  GUM_CONSTRUCTOR(IDatabaseTable::HandlerSafe);
373  }
374 
375 
376  // copy constructor
377  template < typename T_DATA, template < typename > class ALLOC >
378  INLINE IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::HandlerSafe(
379  const typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe& h) :
380  IDatabaseTable< T_DATA, ALLOC >::Handler(h) {
381  __attachHandler();
382  GUM_CONS_CPY(IDatabaseTable::HandlerSafe);
383  }
384 
385 
386  // move constructor
387  template < typename T_DATA, template < typename > class ALLOC >
388  INLINE IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::HandlerSafe(
389  typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&& h) :
390  IDatabaseTable< T_DATA, ALLOC >::Handler(std::move(h)) {
391  __attachHandler();
392  GUM_CONS_MOV(IDatabaseTable::HandlerSafe);
393  }
394 
395 
396  // destructor
397  template < typename T_DATA, template < typename > class ALLOC >
398  INLINE IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::~HandlerSafe() {
399  __detachHandler();
400  GUM_DESTRUCTOR(IDatabaseTable::HandlerSafe);
401  }
402 
403 
404  // copy operator
405  template < typename T_DATA, template < typename > class ALLOC >
406  INLINE typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&
407  IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::operator=(
408  const typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe& h) {
409  if (this->__db != h.__db) {
410  __detachHandler();
411  this->__db = h.__db;
412  __attachHandler();
413  }
414 
415  IDatabaseTable< T_DATA, ALLOC >::Handler::operator=(h);
416  return *this;
417  }
418 
419 
420  // copy operator
421  template < typename T_DATA, template < typename > class ALLOC >
422  INLINE typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&
423  IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::
424  operator=(const typename IDatabaseTable< T_DATA, ALLOC >::Handler& h) {
425  return this->operator=(
426  dynamic_cast< const IDatabaseTable< T_DATA, ALLOC >::HandlerSafe& >(h));
427  }
428 
429 
430  // move operator
431  template < typename T_DATA, template < typename > class ALLOC >
432  INLINE typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&
433  IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::
434  operator=(typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&& h) {
435  if (this->__db != h.__db) {
436  __detachHandler();
437  this->__db = h.__db;
438  __attachHandler();
439  }
440 
441  IDatabaseTable< T_DATA, ALLOC >::Handler::operator=(std::move(h));
442  return *this;
443  }
444 
445 
446  // move operator
447  template < typename T_DATA, template < typename > class ALLOC >
448  INLINE typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&
449  IDatabaseTable< T_DATA, ALLOC >::HandlerSafe::
450  operator=(typename IDatabaseTable< T_DATA, ALLOC >::Handler&& h) {
451  return this->operator=(std::move(
452  dynamic_cast< IDatabaseTable< T_DATA, ALLOC >::HandlerSafe& >(h)));
453  }
454 
455 
456  // ===========================================================================
457  // Database Tables
458  // ===========================================================================
459 
460  // returns the allocator of the database
461  template < typename T_DATA, template < typename > class ALLOC >
462  INLINE ALLOC< T_DATA > IDatabaseTable< T_DATA, ALLOC >::getAllocator() const {
463  return ALLOC< T_DATA >(*this);
464  }
465 
466 
467  // create the end iterators
468  template < typename T_DATA, template < typename > class ALLOC >
469  void IDatabaseTable< T_DATA, ALLOC >::__createEndIterators() {
470  const IDatabaseTable< T_DATA, ALLOC >& db = *this;
471  ALLOC< iterator > allocator1(*this);
472  __end = allocator1.allocate(1);
473  try {
474  allocator1.construct(__end, db);
475  } catch (...) {
476  allocator1.deallocate(__end, 1);
477  throw;
478  }
479 
480  ALLOC< iterator_safe > allocator2(*this);
481  try {
482  __end_safe = allocator2.allocate(1);
483  try {
484  allocator2.construct(__end_safe, *this);
485  } catch (...) {
486  allocator2.deallocate(__end_safe, 1);
487  throw;
488  }
489  } catch (...) {
490  allocator1.destroy(__end);
491  allocator1.deallocate(__end, 1);
492  throw;
493  }
494  }
495 
496 
497  // default constructor
498  template < typename T_DATA, template < typename > class ALLOC >
499  template < template < typename > class VARALLOC,
500  template < typename >
501  class MISSALLOC >
502  IDatabaseTable< T_DATA, ALLOC >::IDatabaseTable(
503  const typename IDatabaseTable< T_DATA, ALLOC >::template MissingValType<
504  MISSALLOC >& missing_symbols,
505  const std::vector< std::string, VARALLOC< std::string > >& var_names,
506  const ALLOC< T_DATA >& alloc) :
507  ALLOC< T_DATA >(alloc),
508  _variable_names(alloc), _rows(alloc), _missing_symbols(alloc),
509  _has_row_missing_val(alloc), __list_of_safe_handlers(alloc) {
510  // copy the names
511  _variable_names.reserve(var_names.size());
512  for (const auto& name : var_names)
513  _variable_names.push_back(name);
514 
515  // copy the missing symbols
516  _missing_symbols.reserve(missing_symbols.size());
517  for (const auto& missing_symbol : missing_symbols)
518  _missing_symbols.push_back(missing_symbol);
519 
520  // create the end iterators
521  __createEndIterators();
522 
523  GUM_CONSTRUCTOR(IDatabaseTable);
524  }
525 
526 
527  // copy constructor with a given allocator
528  template < typename T_DATA, template < typename > class ALLOC >
529  IDatabaseTable< T_DATA, ALLOC >::IDatabaseTable(
530  const IDatabaseTable< T_DATA, ALLOC >& from,
531  const typename IDatabaseTable< T_DATA, ALLOC >::allocator_type& alloc) :
532  ALLOC< T_DATA >(alloc),
533  _variable_names(from._variable_names, alloc), _rows(from._rows, alloc),
534  _missing_symbols(from._missing_symbols, alloc),
535  _has_row_missing_val(from._has_row_missing_val, alloc),
536  _max_nb_threads(from._max_nb_threads),
537  _min_nb_rows_per_thread(from._min_nb_rows_per_thread),
538  __list_of_safe_handlers(alloc) {
539  // create the end iterators
540  __createEndIterators();
541 
542  GUM_CONS_CPY(IDatabaseTable);
543  }
544 
545 
546  // copy constructor
547  template < typename T_DATA, template < typename > class ALLOC >
548  IDatabaseTable< T_DATA, ALLOC >::IDatabaseTable(
549  const IDatabaseTable< T_DATA, ALLOC >& from) :
550  IDatabaseTable< T_DATA, ALLOC >(from, from.getAllocator()) {}
551 
552 
553  // move constructor with a given allocator
554  template < typename T_DATA, template < typename > class ALLOC >
555  IDatabaseTable< T_DATA, ALLOC >::IDatabaseTable(
556  IDatabaseTable< T_DATA, ALLOC >&& from,
557  const typename IDatabaseTable< T_DATA, ALLOC >::allocator_type& alloc) :
558  ALLOC< T_DATA >(alloc),
559  _variable_names(std::move(from._variable_names), alloc),
560  _rows(std::move(from._rows), alloc),
561  _missing_symbols(std::move(from._missing_symbols), alloc),
562  _has_row_missing_val(std::move(from._has_row_missing_val), alloc),
563  _max_nb_threads(from._max_nb_threads),
564  _min_nb_rows_per_thread(from._min_nb_rows_per_thread),
565  __list_of_safe_handlers(alloc) {
566  // create the end iterators
567  __createEndIterators();
568 
569  GUM_CONS_MOV(IDatabaseTable);
570  }
571 
572 
573  // move constructor
574  template < typename T_DATA, template < typename > class ALLOC >
575  IDatabaseTable< T_DATA, ALLOC >::IDatabaseTable(
576  IDatabaseTable< T_DATA, ALLOC >&& from) :
577  IDatabaseTable< T_DATA, ALLOC >(std::move(from), from.getAllocator()) {}
578 
579 
580  // destructor
581  template < typename T_DATA, template < typename > class ALLOC >
582  IDatabaseTable< T_DATA, ALLOC >::~IDatabaseTable() {
583  // indicate to all the handlers that we are destructing the database
584  __safe_handlers_mutex.lock();
585  for (auto handler : __list_of_safe_handlers) {
586  handler->__db = nullptr;
587  handler->__row = nullptr;
588  handler->__end_index = 0;
589  handler->__index = 0;
590  }
591  __safe_handlers_mutex.unlock();
592 
593  ALLOC< iterator > allocator1(this->getAllocator());
594  allocator1.destroy(__end);
595  allocator1.deallocate(__end, 1);
596 
597  ALLOC< iterator_safe > allocator2(this->getAllocator());
598  allocator2.destroy(__end_safe);
599  allocator2.deallocate(__end_safe, 1);
600 
601  GUM_DESTRUCTOR(IDatabaseTable);
602  }
603 
604 
605  // copy operator
606  template < typename T_DATA, template < typename > class ALLOC >
607  IDatabaseTable< T_DATA, ALLOC >& IDatabaseTable< T_DATA, ALLOC >::
608  operator=(const IDatabaseTable< T_DATA, ALLOC >& from) {
609  if (this != &from) {
610  // invalidate the current handlers
611  __safe_handlers_mutex.lock();
612  for (auto handler : __list_of_safe_handlers) {
613  handler->__db = nullptr;
614  handler->__row = nullptr;
615  handler->__end_index = 0;
616  handler->__index = 0;
617  }
618  __list_of_safe_handlers.clear();
619  __safe_handlers_mutex.unlock();
620 
621  _rows = from._rows;
622  _variable_names = from._variable_names;
623  _missing_symbols = from._missing_symbols;
624  _has_row_missing_val = from._has_row_missing_val;
625  _max_nb_threads = from._max_nb_threads;
626  _min_nb_rows_per_thread = from._min_nb_rows_per_thread;
627 
628  // update the end iterators
629  const std::size_t db_size = _rows.size();
630  __end->__index = db_size;
631  __end->__end_index = db_size;
632  __end_safe->__index = db_size;
633  __end_safe->__end_index = db_size;
634  }
635 
636  return *this;
637  }
638 
639 
640  // move operator
641  template < typename T_DATA, template < typename > class ALLOC >
642  IDatabaseTable< T_DATA, ALLOC >& IDatabaseTable< T_DATA, ALLOC >::
643  operator=(IDatabaseTable< T_DATA, ALLOC >&& from) {
644  if (this != &from) {
645  // invalidate the current handlers
646  __safe_handlers_mutex.lock();
647  for (auto handler : __list_of_safe_handlers) {
648  handler->__db = nullptr;
649  handler->__row = nullptr;
650  handler->__end_index = 0;
651  handler->__index = 0;
652  }
653  __safe_handlers_mutex.unlock();
654 
655  _rows = std::move(from._rows);
656  _variable_names = std::move(from._variable_names);
657  _missing_symbols = std::move(from._missing_symbols);
658  _has_row_missing_val = std::move(from._has_row_missing_val);
659  _max_nb_threads = from._max_nb_threads;
660  _min_nb_rows_per_thread = from._min_nb_rows_per_thread;
661 
662  // update the end iterators
663  const std::size_t db_size = _rows.size();
664  __end->__index = db_size;
665  __end->__end_index = db_size;
666  __end_safe->__index = db_size;
667  __end_safe->__end_index = db_size;
668  }
669 
670  return *this;
671  }
672 
673 
674  // returns a new unsafe handler pointing to the beginning of the database
675  template < typename T_DATA, template < typename > class ALLOC >
676  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler
677  IDatabaseTable< T_DATA, ALLOC >::begin() const {
678  return Handler(*this);
679  }
680 
681 
682  // returns a new safe handler pointing to the beginning of the database
683  template < typename T_DATA, template < typename > class ALLOC >
684  INLINE typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe
685  IDatabaseTable< T_DATA, ALLOC >::beginSafe() const {
686  return HandlerSafe(*this);
687  }
688 
689 
690  // returns a new unsafe handler pointing to the end of the database
691  template < typename T_DATA, template < typename > class ALLOC >
692  INLINE const typename IDatabaseTable< T_DATA, ALLOC >::Handler&
693  IDatabaseTable< T_DATA, ALLOC >::end() const noexcept {
694  return *__end;
695  }
696 
697 
699  template < typename T_DATA, template < typename > class ALLOC >
700  INLINE const typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe&
701  IDatabaseTable< T_DATA, ALLOC >::endSafe() const noexcept {
702  return *__end_safe;
703  }
704 
705 
706  // returns a new unsafe handler on the database
707  template < typename T_DATA, template < typename > class ALLOC >
708  INLINE typename IDatabaseTable< T_DATA, ALLOC >::Handler
709  IDatabaseTable< T_DATA, ALLOC >::handler() const {
710  return Handler(*this);
711  }
712 
713 
714  // returns a new safe handler on the database
715  template < typename T_DATA, template < typename > class ALLOC >
716  INLINE typename IDatabaseTable< T_DATA, ALLOC >::HandlerSafe
717  IDatabaseTable< T_DATA, ALLOC >::handlerSafe() const {
718  return HandlerSafe(*this);
719  }
720 
721 
722  // returns the content of the database
723  template < typename T_DATA, template < typename > class ALLOC >
724  INLINE const typename IDatabaseTable< T_DATA,
725  ALLOC >::template Matrix< T_DATA >&
726  IDatabaseTable< T_DATA, ALLOC >::content() const noexcept {
727  return _rows;
728  }
729 
730 
732  template < typename T_DATA, template < typename > class ALLOC >
733  bool IDatabaseTable< T_DATA, ALLOC >::hasMissingValues() const {
734  for (const auto& status : _has_row_missing_val)
735  if (status == IsMissing::True) return true;
736  return false;
737  }
738 
739 
741  template < typename T_DATA, template < typename > class ALLOC >
742  INLINE bool IDatabaseTable< T_DATA, ALLOC >::hasMissingValues(
743  const std::size_t k) const {
744  return _has_row_missing_val[k] == IsMissing::True;
745  }
746 
747 
748  // returns the variable names for all the columns
749  template < typename T_DATA, template < typename > class ALLOC >
750  INLINE const std::vector< std::string, ALLOC< std::string > >&
751  IDatabaseTable< T_DATA, ALLOC >::variableNames() const noexcept {
752  return _variable_names;
753  }
754 
755 
756  // sets the names of the variables
757  template < typename T_DATA, template < typename > class ALLOC >
758  template < template < typename > class OTHER_ALLOC >
759  void IDatabaseTable< T_DATA, ALLOC >::setVariableNames(
760  const std::vector< std::string, OTHER_ALLOC< std::string > >& names,
761  const bool from_external_object) {
762  // copy the variable names into a vector allocated with the allocator
763  // used by the database
764  const std::size_t size = names.size();
765  DBVector< std::string > variable_names(size);
766  for (std::size_t i = 0; i < size; ++i)
767  variable_names[i] = names[i];
768 
769  this->setVariableNames(variable_names, from_external_object);
770  }
771 
772 
774  template < typename T_DATA, template < typename > class ALLOC >
775  INLINE const std::string&
776  IDatabaseTable< T_DATA, ALLOC >::variableName(const std::size_t k) const {
777  if (_variable_names.size() <= k)
778  GUM_ERROR(OutOfBounds, "the database does not contain Column #" << k);
779  return _variable_names[k];
780  }
781 
782 
784  template < typename T_DATA, template < typename > class ALLOC >
785  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::columnFromVariableName(
786  const std::string& name) const {
787  const std::size_t size = _variable_names.size();
788  for (std::size_t i = 0; i < size; ++i)
789  if (_variable_names[i] == name) return i;
790 
791  GUM_ERROR(UndefinedElement,
792  "the database contains no column whose name is " << name);
793  }
794 
795 
797  template < typename T_DATA, template < typename > class ALLOC >
798  INLINE
799  typename IDatabaseTable< T_DATA, ALLOC >::template DBVector< std::size_t >
800  IDatabaseTable< T_DATA, ALLOC >::columnsFromVariableName(
801  const std::string& name) const {
802  const std::size_t size = _variable_names.size();
803  DBVector< std::size_t > cols;
804  for (std::size_t i = 0; i < size; ++i)
805  if (_variable_names[i] == name) cols.push_back(i);
806 
807  if (cols.empty())
808  GUM_ERROR(UndefinedElement,
809  "the database contains no column whose name is " << name);
810 
811  return cols;
812  }
813 
814 
815  // returns the number of variables (columns) of the database
816  template < typename T_DATA, template < typename > class ALLOC >
817  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::nbVariables() const
818  noexcept {
819  return _variable_names.size();
820  }
821 
822 
823  // returns the number of records in the database
824  template < typename T_DATA, template < typename > class ALLOC >
825  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::size() const noexcept {
826  return _rows.size();
827  }
828 
829 
830  // returns the number of records in the database
831  template < typename T_DATA, template < typename > class ALLOC >
832  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::nbRows() const noexcept {
833  return _rows.size();
834  }
835 
836 
837  // indicates whether the database contains some records or not
838  template < typename T_DATA, template < typename > class ALLOC >
839  INLINE bool IDatabaseTable< T_DATA, ALLOC >::empty() const noexcept {
840  return _rows.empty();
841  }
842 
843 
844  // update the handlers when the size of the database changes
845  template < typename T_DATA, template < typename > class ALLOC >
846  void IDatabaseTable< T_DATA, ALLOC >::__updateHandlers(
847  std::size_t new_size) const {
848  const std::size_t db_size = _rows.size();
849 
850  __safe_handlers_mutex.lock();
851  for (auto handler : __list_of_safe_handlers) {
852  if ((handler->__end_index == db_size)
853  || (handler->__end_index > new_size)) {
854  handler->__end_index = new_size;
855  // there is no need to update the index because, in safe handlers,
856  // we always check that the index is less than end_index when trying
857  // to access the rows
858  }
859  }
860  __safe_handlers_mutex.unlock();
861 
862  // update the end iterators
863  __end->__index = new_size;
864  __end->__end_index = new_size;
865  __end_safe->__index = new_size;
866  __end_safe->__end_index = new_size;
867  }
868 
869 
870  // attach a new handler to the database
871  template < typename T_DATA, template < typename > class ALLOC >
872  INLINE void IDatabaseTable< T_DATA, ALLOC >::__attachHandler(
873  HandlerSafe* handler) const {
874  __safe_handlers_mutex.lock();
875  __list_of_safe_handlers.push_back(handler);
876  __safe_handlers_mutex.unlock();
877  }
878 
879 
880  // detach a handler
881  template < typename T_DATA, template < typename > class ALLOC >
882  void IDatabaseTable< T_DATA, ALLOC >::__detachHandler(
883  HandlerSafe* handler) const {
884  __safe_handlers_mutex.lock();
885 
886  for (auto iter = __list_of_safe_handlers.rbegin();
887  iter != __list_of_safe_handlers.rend();
888  ++iter) {
889  if (*iter == handler) {
890  *iter = __list_of_safe_handlers.back();
891  __list_of_safe_handlers.pop_back();
892  break;
893  }
894  }
895 
896  __safe_handlers_mutex.unlock();
897  }
898 
899 
900  // checks whether a new row has the same size as the rest of the database
901  template < typename T_DATA, template < typename > class ALLOC >
902  INLINE bool IDatabaseTable< T_DATA, ALLOC >::_isRowSizeOK(
903  const std::size_t size) const {
904  return (size == _variable_names.size());
905  }
906 
907 
908  // insert a new row at the end of the database
909  template < typename T_DATA, template < typename > class ALLOC >
910  template < template < typename > class OTHER_ALLOC >
911  void IDatabaseTable< T_DATA, ALLOC >::insertRow(
912  const std::vector< std::string, OTHER_ALLOC< std::string > >& new_row) {
913  const std::size_t size = new_row.size();
914  std::vector< std::string, ALLOC< std::string > > good_typed_row(size);
915  for (std::size_t i = 0; i < size; ++i)
916  good_typed_row[i] = new_row[i];
917  this->insertRow(good_typed_row);
918  }
919 
920 
921  // insert a new DBRow at the end of the database
922  template < typename T_DATA, template < typename > class ALLOC >
923  void IDatabaseTable< T_DATA, ALLOC >::insertRow(
924  typename IDatabaseTable< T_DATA, ALLOC >::template Row< T_DATA >&& new_row,
925  const typename IDatabaseTable< T_DATA, ALLOC >::IsMissing
926  contains_missing) {
927  // check that the size of the row is the same as the rest of the database
928  if (!_isRowSizeOK(new_row.size()))
929  GUM_ERROR(SizeError,
930  "the new row is of size "
931  << new_row.size()
932  << ", which is different from the number of columns "
933  << "of the database, i.e., " << _variable_names.size());
934 
935  __updateHandlers(_rows.size() + 1);
936  _rows.push_back(std::move(new_row));
937  try {
938  _has_row_missing_val.push_back(contains_missing);
939  } catch (...) {
940  _rows.pop_back();
941  throw;
942  }
943  }
944 
945 
946  // insert a new DBRow at the end of the database
947  template < typename T_DATA, template < typename > class ALLOC >
948  INLINE void IDatabaseTable< T_DATA, ALLOC >::insertRow(
949  const typename IDatabaseTable< T_DATA, ALLOC >::template Row< T_DATA >& row,
950  const typename IDatabaseTable< T_DATA, ALLOC >::IsMissing
951  contains_missing) {
952  this->insertRow(
953  typename IDatabaseTable< T_DATA, ALLOC >::template Row< T_DATA >(row),
954  contains_missing);
955  }
956 
957 
958  // insert a set of new DBRow at the end of the database
959  template < typename T_DATA, template < typename > class ALLOC >
960  void IDatabaseTable< T_DATA, ALLOC >::insertRows(
961  typename IDatabaseTable< T_DATA, ALLOC >::template Matrix< T_DATA >&&
962  new_rows,
963  const typename IDatabaseTable< T_DATA, ALLOC >::template DBVector<
964  typename IDatabaseTable< T_DATA, ALLOC >::IsMissing >&
965  rows_have_missing_vals) {
966  if (new_rows.empty()) return;
967 
968  // check that the missing values indicators vector has the same size
969  // as the new rows
970  if (rows_have_missing_vals.size() != new_rows.size())
971  GUM_ERROR(
972  SizeError,
973  "the number of new rows (i.e., "
974  << new_rows.size()
975  << ") is different from the number of missing values indicators ("
976  << rows_have_missing_vals.size());
977 
978  // check that all the rows have the same size
979  const std::size_t new_size = new_rows[0].size();
980 
981  for (const auto& row : new_rows) {
982  if (row.size() != new_size) {
983  GUM_ERROR(SizeError,
984  "all the new rows do not have the same number of columns");
985  }
986  }
987 
988  // check that the sizes of the new rows are the same as the rest of
989  // the database
990  if (!_isRowSizeOK(new_size)) {
991  GUM_ERROR(SizeError,
992  "the new rows have "
993  << new_size
994  << " columns, which is different from the number of columns "
995  << "of the database, i.e., " << _variable_names.size());
996  }
997 
998  const std::size_t nb_new_rows = new_rows.size();
999  const std::size_t new_db_size = _rows.size() + nb_new_rows;
1000 
1001  _rows.reserve(new_db_size);
1002  _has_row_missing_val.reserve(new_db_size);
1003 
1004  for (std::size_t i = std::size_t(0); i < nb_new_rows; ++i) {
1005  _rows.push_back(std::move(new_rows[i]));
1006  _has_row_missing_val.push_back(rows_have_missing_vals[i]);
1007  }
1008 
1009  __updateHandlers(new_db_size);
1010  }
1011 
1012 
1013  // insert a set of new DBRow at the end of the database
1014  template < typename T_DATA, template < typename > class ALLOC >
1015  void IDatabaseTable< T_DATA, ALLOC >::insertRows(
1016  const typename IDatabaseTable< T_DATA, ALLOC >::template Matrix< T_DATA >&
1017  new_rows,
1018  const typename IDatabaseTable< T_DATA, ALLOC >::template DBVector<
1019  typename IDatabaseTable< T_DATA, ALLOC >::IsMissing >&
1020  rows_have_missing_vals) {
1021  if (new_rows.empty()) return;
1022 
1023  // check that the missing values indicators vector has the same size
1024  // as the new rows
1025  if (rows_have_missing_vals.size() != new_rows.size())
1026  GUM_ERROR(
1027  SizeError,
1028  "the number of new rows (i.e., "
1029  << new_rows.size()
1030  << ") is different from the number of missing values indicators ("
1031  << rows_have_missing_vals.size());
1032 
1033  // check that all the rows have the same size
1034  const std::size_t new_size = new_rows[0].size();
1035 
1036  for (const auto& row : new_rows) {
1037  if (row.size() != new_size) {
1038  GUM_ERROR(SizeError,
1039  "all the new rows do not have the same number of columns");
1040  }
1041  }
1042 
1043  // check that the sizes of the new rows are the same as the rest of
1044  // the database
1045  std::size_t db_size = _rows.size();
1046 
1047  if (!_isRowSizeOK(new_size)) {
1048  GUM_ERROR(SizeError,
1049  "the new rows have "
1050  << new_size
1051  << " columns, which is different from the number of columns "
1052  << "of the database, i.e., " << _variable_names.size());
1053  }
1054 
1055  const std::size_t nb_new_rows = new_rows.size();
1056  const std::size_t new_db_size = _rows.size() + nb_new_rows;
1057 
1058  _rows.reserve(new_db_size);
1059  _has_row_missing_val.reserve(new_db_size);
1060 
1061  for (std::size_t i = std::size_t(0); i < nb_new_rows; ++i) {
1062  _rows.push_back(new_rows[i]);
1063  _has_row_missing_val.push_back(rows_have_missing_vals[i]);
1064  }
1065 
1066  __updateHandlers(db_size);
1067  }
1068 
1069 
1070  // erase a given row
1071  template < typename T_DATA, template < typename > class ALLOC >
1072  INLINE void IDatabaseTable< T_DATA, ALLOC >::eraseRow(std::size_t index) {
1073  const std::size_t db_size = _rows.size();
1074 
1075  if (index < db_size) {
1076  __updateHandlers(db_size - 1);
1077  _rows.erase(_rows.begin() + index);
1078  _has_row_missing_val.erase(_has_row_missing_val.begin() + index);
1079  }
1080  }
1081 
1082 
1083  // erase the last row
1084  template < typename T_DATA, template < typename > class ALLOC >
1085  INLINE void IDatabaseTable< T_DATA, ALLOC >::eraseLastRow() {
1086  const std::size_t db_size = _rows.size();
1087 
1088  if (db_size) {
1089  __updateHandlers(db_size - 1);
1090  _rows.pop_back();
1091  _has_row_missing_val.pop_back();
1092  }
1093  }
1094 
1095 
1096  // erase the first row
1097  template < typename T_DATA, template < typename > class ALLOC >
1098  INLINE void IDatabaseTable< T_DATA, ALLOC >::eraseFirstRow() {
1099  const std::size_t db_size = _rows.size();
1100 
1101  if (db_size) {
1102  __updateHandlers(db_size - 1);
1103  _rows.erase(_rows.begin());
1104  _has_row_missing_val.erase(_has_row_missing_val.begin());
1105  }
1106  }
1107 
1108 
1109  // erase all the rows
1110  template < typename T_DATA, template < typename > class ALLOC >
1111  INLINE void IDatabaseTable< T_DATA, ALLOC >::eraseAllRows() {
1112  __updateHandlers(0);
1113  _rows.clear();
1114  _has_row_missing_val.clear();
1115  }
1116 
1117 
1118  // erase the k first rows
1119  template < typename T_DATA, template < typename > class ALLOC >
1120  INLINE void
1121  IDatabaseTable< T_DATA, ALLOC >::eraseFirstRows(const std::size_t nb_rows) {
1122  const std::size_t db_size = _rows.size();
1123 
1124  if (nb_rows >= db_size) {
1125  eraseAllRows();
1126  } else {
1127  __updateHandlers(db_size - nb_rows);
1128  _rows.erase(_rows.begin(), _rows.begin() + nb_rows);
1129  _has_row_missing_val.erase(_has_row_missing_val.begin(),
1130  _has_row_missing_val.begin() + nb_rows);
1131  }
1132  }
1133 
1134 
1135  // erase the k last rows
1136  template < typename T_DATA, template < typename > class ALLOC >
1137  INLINE void
1138  IDatabaseTable< T_DATA, ALLOC >::eraseLastRows(const std::size_t nb_rows) {
1139  const std::size_t db_size = _rows.size();
1140 
1141  if (nb_rows >= db_size) {
1142  eraseAllRows();
1143  } else {
1144  __updateHandlers(db_size - nb_rows);
1145  _rows.erase(_rows.begin() + (db_size - nb_rows), _rows.begin() + db_size);
1146  _has_row_missing_val.erase(_has_row_missing_val.begin()
1147  + (db_size - nb_rows),
1148  _has_row_missing_val.begin() + db_size);
1149  }
1150  }
1151 
1152 
1153  // erase the rows from the debth to the endth (not included)
1154  template < typename T_DATA, template < typename > class ALLOC >
1155  INLINE void IDatabaseTable< T_DATA, ALLOC >::eraseRows(std::size_t deb,
1156  std::size_t end) {
1157  if (deb > end) std::swap(deb, end);
1158 
1159  const std::size_t db_size = _rows.size();
1160 
1161  if (end >= db_size) {
1162  if (deb >= db_size) {
1163  return;
1164  } else {
1165  eraseLastRows(db_size - deb);
1166  }
1167  } else {
1168  __updateHandlers(db_size - (end - deb));
1169  _rows.erase(_rows.begin() + deb, _rows.begin() + end);
1170  _has_row_missing_val.erase(_has_row_missing_val.begin() + deb,
1171  _has_row_missing_val.begin() + end);
1172  }
1173  }
1174 
1175 
1176  // erase the content of the database, including the names of the variables
1177  template < typename T_DATA, template < typename > class ALLOC >
1178  INLINE void IDatabaseTable< T_DATA, ALLOC >::clear() {
1179  __updateHandlers(0);
1180  _rows.clear();
1181  _has_row_missing_val.clear();
1182  _variable_names.clear();
1183  }
1184 
1185 
1186  // returns the set of symbols for the missing values
1187  template < typename T_DATA, template < typename > class ALLOC >
1188  INLINE const std::vector< std::string, ALLOC< std::string > >&
1189  IDatabaseTable< T_DATA, ALLOC >::missingSymbols() const {
1190  return _missing_symbols;
1191  }
1192 
1193 
1195  template < typename T_DATA, template < typename > class ALLOC >
1196  void IDatabaseTable< T_DATA, ALLOC >::setMaxNbThreads(
1197  const std::size_t nb) const {
1198  if (nb == std::size_t(0))
1199  _max_nb_threads = std::size_t(1);
1200  else
1201  _max_nb_threads = nb;
1202  }
1203 
1204 
1206  template < typename T_DATA, template < typename > class ALLOC >
1207  INLINE std::size_t IDatabaseTable< T_DATA, ALLOC >::nbThreads() const {
1208  return _max_nb_threads;
1209  }
1210 
1211 
1214  template < typename T_DATA, template < typename > class ALLOC >
1215  void IDatabaseTable< T_DATA, ALLOC >::setMinNbRowsPerThread(
1216  const std::size_t nb) const {
1217  if (nb == std::size_t(0))
1218  _min_nb_rows_per_thread = std::size_t(1);
1219  else
1220  _min_nb_rows_per_thread = nb;
1221  }
1222 
1223 
1225  template < typename T_DATA, template < typename > class ALLOC >
1226  INLINE std::size_t
1227  IDatabaseTable< T_DATA, ALLOC >::minNbRowsPerThread() const {
1228  return _min_nb_rows_per_thread;
1229  }
1230 
1231 
1233  template < template < typename > class ALLOC >
1234  void IDatabaseTableInsert4DBCell< ALLOC, true >::insertRows(
1235  const typename IDatabaseTableInsert4DBCell< ALLOC, true >::
1236  template DBVector< DBVector< std::string > >& new_rows) {
1237  for (const auto& new_row : new_rows)
1238  this->insertRow(new_row);
1239  }
1240 
1241 
1243  template < template < typename > class ALLOC >
1244  void IDatabaseTableInsert4DBCell< ALLOC, false >::insertRows(
1245  const typename IDatabaseTableInsert4DBCell< ALLOC, false >::
1246  template DBVector< DBVector< std::string > >& new_rows) {
1247  for (const auto& new_row : new_rows)
1248  this->insertRow(new_row);
1249  }
1250 
1251 
1253  template < typename T_DATA, template < typename > class ALLOC >
1254  void
1255  IDatabaseTable< T_DATA, ALLOC >::setAllRowsWeight(const double new_weight) {
1256  // determine the number of threads to use and the number of rows
1257  // they should process
1258  std::vector< std::pair< std::size_t, std::size_t > > ranges;
1259  const std::size_t db_size = nbRows();
1260  std::size_t nb_threads = db_size / _min_nb_rows_per_thread;
1261  if (nb_threads < 1)
1262  nb_threads = 1;
1263  else if (nb_threads > _max_nb_threads)
1264  nb_threads = _max_nb_threads;
1265  std::size_t nb_rows_per_thread = db_size / nb_threads;
1266  std::size_t rest_rows = db_size - nb_rows_per_thread * nb_threads;
1267 
1268  // assign to threads the ranges over which they should change the
1269  // rows weights
1270  std::size_t begin_index = std::size_t(0);
1271  for (std::size_t i = std::size_t(0); i < nb_threads; ++i) {
1272  std::size_t end_index = begin_index + nb_rows_per_thread;
1273  if (rest_rows != std::size_t(0)) {
1274  ++end_index;
1275  --rest_rows;
1276  }
1277  ranges.push_back(
1278  std::pair< std::size_t, std::size_t >(begin_index, end_index));
1279  begin_index = end_index;
1280  }
1281 
1282  // perform the assignment:
1283  // launch the threads
1284  // here we use openMP for launching the threads because, experimentally,
1285  // it seems to provide results that are twice as fast as the results
1286  // with the std::thread
1287 # pragma omp parallel num_threads(int(nb_threads))
1288  {
1289  // get the number of the thread
1290  const std::size_t this_thread = getThreadNumber();
1291  const std::size_t begin_index = ranges[this_thread].first;
1292  const std::size_t end_index = ranges[this_thread].second;
1293 
1294  for (std::size_t i = begin_index; i < end_index; ++i) {
1295  _rows[i].setWeight(new_weight);
1296  }
1297  }
1298  }
1299 
1301  template < typename T_DATA, template < typename > class ALLOC >
1302  void IDatabaseTable< T_DATA, ALLOC >::setWeight(const std::size_t i,
1303  const double weight) {
1304  // check that i is less than the number of rows
1305  const std::size_t dbsize = nbRows();
1306  if (i >= dbsize) {
1307  std::string str;
1308  switch (i) {
1309  case 1: str = "st"; break;
1310  case 2: str = "nd"; break;
1311  default: str = "th";
1312  }
1313  GUM_ERROR(OutOfBounds,
1314  "it is impossible to set the weight of the "
1315  << i << str << " record because the database contains only "
1316  << nbRows() << " records");
1317  }
1318 
1319  // check that the weight is positive
1320  if (weight < 0) {
1321  std::string str;
1322  switch (i) {
1323  case 1: str = "st"; break;
1324  case 2: str = "nd"; break;
1325  default: str = "th";
1326  }
1327  GUM_ERROR(OutOfBounds,
1328  "it is impossible to set "
1329  << weight << " as a weight of the " << i << str
1330  << " record because this weight is negative");
1331  }
1332 
1333  _rows[i].setWeight(weight);
1334  }
1335 
1336 
1338  template < typename T_DATA, template < typename > class ALLOC >
1339  double IDatabaseTable< T_DATA, ALLOC >::weight(const std::size_t i) const {
1340  // check that i is less than the number of rows
1341  const std::size_t dbsize = nbRows();
1342  if (i >= dbsize) {
1343  std::string str;
1344  switch (i) {
1345  case 1: str = "st"; break;
1346  case 2: str = "nd"; break;
1347  default: str = "th";
1348  }
1349  GUM_ERROR(OutOfBounds,
1350  "it is impossible to get the weight of the "
1351  << i << str << " record because the database contains only "
1352  << nbRows() << " records");
1353  }
1354 
1355  return _rows[i].weight();
1356  }
1357 
1358 
1360  template < typename T_DATA, template < typename > class ALLOC >
1361  double IDatabaseTable< T_DATA, ALLOC >::weight() const {
1362  double w = 0.0;
1363  for (const auto& row : _rows)
1364  w += row.weight();
1365  return w;
1366  }
1367 
1368 
1369  } /* namespace learning */
1370 
1371 } /* namespace gum */
1372 
1373 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
unsigned int getThreadNumber()
Get the calling thread id.
STL namespace.
void swap(HashTable< LpCol, double > *&a, HashTable< LpCol, double > *&b)
Swap the addresses of two pointers to hashTables.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
bool operator==(const TiXmlString &a, const TiXmlString &b)
Definition: tinystr.h:243
Handler(const IDatabaseTable< T_DATA, ALLOC > &db)
default constructor
LpExpr operator*(const SCALAR &lhs, const LpCol &rhs)
Overload of operator * between a scalar and a variable.
bool operator!=(const TiXmlString &a, const TiXmlString &b)
Definition: tinystr.h:251
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55