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