1
/*************************************************************************
3
* Copyright (c) 2010 Kohei Yoshida
5
* Permission is hereby granted, free of charge, to any person
6
* obtaining a copy of this software and associated documentation
7
* files (the "Software"), to deal in the Software without
8
* restriction, including without limitation the rights to use,
9
* copy, modify, merge, publish, distribute, sublicense, and/or sell
10
* copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following
14
* The above copyright notice and this permission notice shall be
15
* included in all copies or substantial portions of the Software.
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
* OTHER DEALINGS IN THE SOFTWARE.
26
************************************************************************/
28
#ifndef __MDDS_MIXED_TYPE_MATRIX_STORAGE_HPP__
29
#define __MDDS_MIXED_TYPE_MATRIX_STORAGE_HPP__
33
#include <boost/ptr_container/ptr_vector.hpp>
34
#include <boost/ptr_container/ptr_map.hpp>
40
matrix_storage_filled,
44
enum matrix_init_element_t
46
matrix_init_element_zero,
47
matrix_init_element_empty
50
class matrix_storage_error : public ::mdds::general_error
53
matrix_storage_error(const ::std::string& msg) : general_error(msg) {}
57
* Wrapper class that provides access to the storage internals. This is
58
* used by storage_base::const_iterator to traverse data in different
61
template<typename _StoreType, typename _ElemWrap, typename _RowsWrap>
62
class const_itr_access
64
typedef _StoreType store_type;
65
typedef _ElemWrap element_wrap_type;
66
typedef _RowsWrap rows_wrap_type;
68
typedef typename _StoreType::element element;
70
const_itr_access(const store_type& db) :
72
m_rows_itr(db.get_rows().begin()),
73
m_rows_itr_end(db.get_rows().end())
75
// create iterators for the first row.
80
const_itr_access(const const_itr_access& r) :
82
m_rows_itr(r.m_rows_itr),
83
m_rows_itr_end(r.m_rows_itr_end),
84
m_row_itr(r.m_row_itr),
85
m_row_itr_end(r.m_row_itr_end) {}
88
* Set the current iterator position to the end position.
95
m_rows_itr = m_rows_itr_end;
96
typename store_type::rows_type::const_iterator itr = m_rows_itr_end;
97
--itr; // Move to the last row.
99
// They both need to be at the end position of the last row.
100
m_row_itr = m_row_itr_end = m_rows_wrap(itr).end();
103
bool operator== (const const_itr_access& r) const
105
if (&m_db != &r.m_db)
106
// different storage instances.
112
if (m_rows_itr != r.m_rows_itr)
115
// If the rows iterators are equal, the end positions should be equal
116
// too. No need to check it.
117
assert(m_rows_itr_end == r.m_rows_itr_end);
119
if (m_row_itr != r.m_row_itr)
122
// Same assumption holds here too. See above.
123
assert(m_row_itr_end == r.m_row_itr_end);
127
bool empty() const { return m_db.get_rows().begin() == m_rows_itr_end; }
129
void update_row_itr()
131
m_row_itr = m_rows_wrap(m_rows_itr).begin();
132
m_row_itr_end = m_rows_wrap(m_rows_itr).end();
135
const element& get() const { return m_wrap(m_row_itr); }
139
if (m_row_itr == m_row_itr_end)
143
if (m_row_itr == m_row_itr_end)
145
// Move to the next row.
146
if (m_rows_itr != m_rows_itr_end)
149
if (m_rows_itr == m_rows_itr_end)
160
if (m_rows_itr == m_rows_itr_end)
163
assert(m_row_itr == m_row_itr_end);
168
if (m_row_itr == m_rows_wrap(m_rows_itr).begin())
170
// On the first element of a row.
171
if (m_rows_itr == m_db.get_rows().begin())
172
// already on the first row.
175
// Move up to the previous row, and select its last element.
177
assert(!m_rows_wrap(m_rows_itr).empty());
178
m_row_itr_end = m_rows_wrap(m_rows_itr).end();
179
m_row_itr = m_row_itr_end;
184
// Not on the first element of a row.
190
const store_type& m_db;
191
typename store_type::rows_type::const_iterator m_rows_itr;
192
typename store_type::rows_type::const_iterator m_rows_itr_end;
193
typename store_type::row_type::const_iterator m_row_itr;
194
typename store_type::row_type::const_iterator m_row_itr_end;
195
element_wrap_type m_wrap;
196
rows_wrap_type m_rows_wrap;
199
template<typename _MatrixType>
203
typedef _MatrixType matrix_type;
205
typedef typename _MatrixType::element element;
206
typedef typename _MatrixType::flag_storage flag_storage;
207
typedef typename _MatrixType::string_type string_type;
208
typedef typename _MatrixType::filled_storage_type filled_storage_type;
209
typedef typename _MatrixType::sparse_storage_type sparse_storage_type;
213
typedef typename filled_storage_type::const_itr_access filled_access_type;
214
typedef typename sparse_storage_type::const_itr_access sparse_access_type;
217
typedef element value_type;
218
typedef element* pointer;
219
typedef element& reference;
220
typedef ptrdiff_t difference_type;
221
typedef ::std::bidirectional_iterator_tag iterator_category;
224
m_const_itr_access(NULL), m_type(matrix_storage_filled)
227
const_iterator(void* p, matrix_storage_t type, bool _end = false) :
228
m_const_itr_access(p), m_type(type)
235
case matrix_storage_filled:
236
get_filled_itr()->set_to_end();
238
case matrix_storage_sparse:
239
get_sparse_itr()->set_to_end();
242
assert(!"unknown storage type");
247
const_iterator(const const_iterator& r) :
248
m_const_itr_access(NULL),
251
if (!r.m_const_itr_access)
256
case matrix_storage_filled:
257
m_const_itr_access = new filled_access_type(*r.get_filled_itr());
259
case matrix_storage_sparse:
260
m_const_itr_access = new sparse_access_type(*r.get_sparse_itr());
263
assert(!"unknown storage type");
271
case matrix_storage_filled:
272
delete get_filled_itr();
274
case matrix_storage_sparse:
275
delete get_sparse_itr();
278
assert(!"unknown storage type");
282
void swap(const_iterator& r)
284
::std::swap(m_type, r.m_type);
285
::std::swap(m_const_itr_access, r.m_const_itr_access);
288
const_iterator& operator=(const const_iterator& r)
294
const_iterator new_itr(r);
299
const element& operator*() const
303
case matrix_storage_filled:
304
return get_filled_itr()->get();
305
case matrix_storage_sparse:
306
return get_sparse_itr()->get();
308
assert(!"unknown storage type");
310
throw matrix_storage_error("unknown storage type");
313
const element* operator->() const
317
case matrix_storage_filled:
318
return &get_filled_itr()->get();
319
case matrix_storage_sparse:
320
return &get_sparse_itr()->get();
322
assert(!"unknown storage type");
327
const element* operator++()
329
bool has_next = false;
332
case matrix_storage_filled:
333
has_next = get_filled_itr()->inc();
335
case matrix_storage_sparse:
336
has_next = get_sparse_itr()->inc();
339
assert(!"unknown storage type");
341
return has_next ? operator->() : NULL;
344
const element* operator--()
346
bool has_next = false;
349
case matrix_storage_filled:
350
has_next = get_filled_itr()->dec();
352
case matrix_storage_sparse:
353
has_next = get_sparse_itr()->dec();
356
assert(!"unknown storage type");
358
return has_next ? operator->() : NULL;
361
bool operator== (const const_iterator& r) const
363
if (m_type != r.m_type)
367
if (!m_const_itr_access)
368
// This instance has empty access. The other one must be empty too.
369
return r.m_const_itr_access == NULL;
371
assert(m_const_itr_access != NULL);
372
assert(r.m_const_itr_access != NULL);
376
case matrix_storage_filled:
377
return *get_filled_itr() == *r.get_filled_itr();
378
case matrix_storage_sparse:
379
return *get_sparse_itr() == *r.get_sparse_itr();
381
assert(!"unknown storage type");
386
bool operator!= (const const_iterator& r) const
388
return !operator==(r);
392
filled_access_type* get_filled_itr()
394
return static_cast<filled_access_type*>(m_const_itr_access);
397
const filled_access_type* get_filled_itr() const
399
return static_cast<const filled_access_type*>(m_const_itr_access);
402
sparse_access_type* get_sparse_itr()
404
return static_cast<sparse_access_type*>(m_const_itr_access);
407
const sparse_access_type* get_sparse_itr() const
409
return static_cast<const sparse_access_type*>(m_const_itr_access);
413
* Stores new'ed instance of const_itr_access of the respective
414
* storage type. TODO: Find out if there is a way to store the
415
* const_itr_access instance in a type-safe way.
417
void* m_const_itr_access;
420
* Matrix storage type which is either filled or sparse.
422
matrix_storage_t m_type;
425
storage_base(matrix_storage_t store_type, matrix_init_element_t init) :
426
m_store_type(store_type), m_init_type(init) {}
428
storage_base(const storage_base& r) :
429
m_store_type(r.m_store_type), m_init_type(r.m_init_type), m_flags(r.m_flags) {}
431
matrix_storage_t get_storage_type() const { return m_store_type; }
434
* the destructor must remain virtual because the derived classes have
435
* different sizes. TODO: Figure out a way to remove the virtual-ness
436
* without leaking memory.
438
virtual ~storage_base() {}
440
const_iterator begin() const
442
switch (m_store_type)
444
case matrix_storage_filled:
446
void* p = static_cast<const filled_storage_type*>(this)->get_const_itr_access();
447
return const_iterator(p, m_store_type);
450
case matrix_storage_sparse:
452
void* p = static_cast<const sparse_storage_type*>(this)->get_const_itr_access();
453
return const_iterator(p, m_store_type);
457
assert(!"unknown storage type");
459
throw matrix_storage_error("unknown storage type");
462
const_iterator end() const
464
switch (m_store_type)
466
case matrix_storage_filled:
468
void* p = static_cast<const filled_storage_type*>(this)->get_const_itr_access();
469
return const_iterator(p, m_store_type, true);
472
case matrix_storage_sparse:
474
void* p = static_cast<const sparse_storage_type*>(this)->get_const_itr_access();
475
return const_iterator(p, m_store_type, true);
479
assert(!"unknown storage type");
481
throw matrix_storage_error("unknown storage type");
484
element& get_element(size_t row, size_t col)
486
switch (m_store_type)
488
case matrix_storage_filled:
489
return static_cast<filled_storage_type*>(this)->get_element(row, col);
490
case matrix_storage_sparse:
491
return static_cast<sparse_storage_type*>(this)->get_element(row, col);
493
assert(!"unknown storage type");
495
throw matrix_storage_error("unknown storage type");
498
matrix_element_t get_type(size_t row, size_t col) const
500
switch (m_store_type)
502
case matrix_storage_filled:
503
return static_cast<const filled_storage_type*>(this)->get_type(row, col);
504
case matrix_storage_sparse:
505
return static_cast<const sparse_storage_type*>(this)->get_type(row, col);
507
assert(!"unknown storage type");
509
throw matrix_storage_error("unknown storage type");
512
double get_numeric(size_t row, size_t col) const
514
switch (m_store_type)
516
case matrix_storage_filled:
517
return static_cast<const filled_storage_type*>(this)->get_numeric(row, col);
518
case matrix_storage_sparse:
519
return static_cast<const sparse_storage_type*>(this)->get_numeric(row, col);
521
assert(!"unknown storage type");
523
throw matrix_storage_error("unknown storage type");
526
const string_type* get_string(size_t row, size_t col) const
528
switch (m_store_type)
530
case matrix_storage_filled:
531
return static_cast<const filled_storage_type*>(this)->get_string(row, col);
532
case matrix_storage_sparse:
533
return static_cast<const sparse_storage_type*>(this)->get_string(row, col);
535
assert(!"unknown storage type");
537
throw matrix_storage_error("unknown storage type");
540
bool get_boolean(size_t row, size_t col) const
542
switch (m_store_type)
544
case matrix_storage_filled:
545
return static_cast<const filled_storage_type*>(this)->get_boolean(row, col);
546
case matrix_storage_sparse:
547
return static_cast<const sparse_storage_type*>(this)->get_boolean(row, col);
549
assert(!"unknown storage type");
551
throw matrix_storage_error("unknown storage type");
556
switch (m_store_type)
558
case matrix_storage_filled:
559
return static_cast<const filled_storage_type*>(this)->rows();
560
case matrix_storage_sparse:
561
return static_cast<const sparse_storage_type*>(this)->rows();
563
assert(!"unknown storage type");
565
throw matrix_storage_error("unknown storage type");
570
switch (m_store_type)
572
case matrix_storage_filled:
573
return static_cast<const filled_storage_type*>(this)->cols();
574
case matrix_storage_sparse:
575
return static_cast<const sparse_storage_type*>(this)->cols();
577
assert(!"unknown storage type");
579
throw matrix_storage_error("unknown storage type");
584
switch (m_store_type)
586
case matrix_storage_filled:
587
static_cast<filled_storage_type*>(this)->transpose();
589
case matrix_storage_sparse:
590
static_cast<sparse_storage_type*>(this)->transpose();
593
assert(!"unknown storage type");
597
void resize(size_t row, size_t col)
599
switch (m_store_type)
601
case matrix_storage_filled:
602
static_cast<filled_storage_type*>(this)->resize(row, col);
604
case matrix_storage_sparse:
605
static_cast<sparse_storage_type*>(this)->resize(row, col);
608
assert(!"unknown storage type");
614
switch (m_store_type)
616
case matrix_storage_filled:
617
static_cast<filled_storage_type*>(this)->clear();
619
case matrix_storage_sparse:
620
static_cast<sparse_storage_type*>(this)->clear();
623
assert(!"unknown storage type");
629
switch (m_store_type)
631
case matrix_storage_filled:
632
return static_cast<filled_storage_type*>(this)->numeric();
633
case matrix_storage_sparse:
634
return static_cast<sparse_storage_type*>(this)->numeric();
636
assert(!"unknown storage type");
638
throw matrix_storage_error("unknown storage type");
643
switch (m_store_type)
645
case matrix_storage_filled:
646
return static_cast<const filled_storage_type*>(this)->empty();
647
case matrix_storage_sparse:
648
return static_cast<const sparse_storage_type*>(this)->empty();
650
assert(!"unknown storage type");
652
throw matrix_storage_error("unknown storage type");
655
storage_base* clone() const
657
switch (m_store_type)
659
case matrix_storage_filled:
660
return static_cast<const filled_storage_type*>(this)->clone();
661
case matrix_storage_sparse:
662
return static_cast<const sparse_storage_type*>(this)->clone();
664
assert(!"unknown storage type");
666
throw matrix_storage_error("unknown storage type");
669
flag_storage& get_flag_storage() { return m_flags; }
672
matrix_init_element_t get_init_type() const { return m_init_type; }
675
matrix_storage_t m_store_type;
676
matrix_init_element_t m_init_type;
677
flag_storage m_flags;
681
* This storage creates instance for every single element, even for the
684
template<typename _MatrixType>
685
class storage_filled : public ::mdds::storage_base<_MatrixType>
687
typedef _MatrixType matrix_type;
688
typedef typename matrix_type::string_type string_type;
691
typedef typename matrix_type::element element;
692
typedef ::boost::ptr_vector<element> row_type;
693
typedef ::boost::ptr_vector<row_type> rows_type;
697
const element& operator() (const typename row_type::const_iterator& itr) const
704
const row_type& operator() (const typename rows_type::const_iterator& itr) const
709
typedef ::mdds::const_itr_access<storage_filled, elem_wrap, rows_wrap> const_itr_access;
711
storage_filled(size_t _rows, size_t _cols, matrix_init_element_t init_type) :
712
storage_base<matrix_type>(matrix_storage_filled, init_type),
716
m_rows.reserve(_rows);
717
for (size_t i = 0; i < _rows; ++i)
719
m_rows.push_back(new row_type);
720
init_row(m_rows.back(), _cols);
724
storage_filled(const storage_filled& r) :
725
storage_base<matrix_type>(r),
727
m_numeric(r.m_numeric),
728
m_valid(r.m_valid) {}
730
virtual ~storage_filled() {}
732
const_itr_access* get_const_itr_access() const
734
return new const_itr_access(*this);
737
element& get_element(size_t row, size_t col)
740
return m_rows.at(row).at(col);
743
matrix_element_t get_type(size_t row, size_t col) const
745
return m_rows.at(row).at(col).m_type;
748
double get_numeric(size_t row, size_t col) const
750
const element& elem = m_rows.at(row).at(col);
753
case element_numeric:
754
return elem.m_numeric;
755
case element_boolean:
756
return static_cast<double>(elem.m_boolean);
764
const string_type* get_string(size_t row, size_t col) const
766
const element& elem = m_rows.at(row).at(col);
767
if (elem.m_type != element_string)
768
throw matrix_storage_error("element type is not string.");
770
return elem.mp_string;
773
bool get_boolean(size_t row, size_t col) const
775
const element& elem = m_rows.at(row).at(col);
776
if (elem.m_type != element_boolean)
777
throw matrix_storage_error("element type is not boolean.");
779
return elem.m_boolean;
784
return m_rows.size();
789
return m_rows.empty() ? 0 : m_rows[0].size();
795
size_t row_size = rows(), col_size = cols();
796
trans_mx.reserve(col_size);
797
for (size_t col = 0; col < col_size; ++col)
799
trans_mx.push_back(new row_type);
800
row_type& trans_row = trans_mx.back();
801
trans_row.reserve(row_size);
802
for (size_t row = 0; row < row_size; ++row)
803
trans_row.push_back(new element(m_rows[row][col]));
805
m_rows.swap(trans_mx);
808
void resize(size_t row, size_t col)
818
size_t cur_rows = rows(), cur_cols = cols();
820
if (!cur_rows || !cur_cols)
822
// current matrix is empty.
824
new_rows.reserve(row);
825
for (size_t i = 0; i < row; ++i)
827
new_rows.push_back(new row_type);
828
init_row(new_rows.back(), col);
830
m_rows.swap(new_rows);
836
// Insert extra rows...
837
size_t new_row_count = row - cur_rows;
839
for (size_t i = 0; i < new_row_count; ++i)
841
m_rows.push_back(new row_type);
842
init_row(m_rows.back(), col);
845
resize_rows(cur_rows-1, cur_cols, col);
847
else if (cur_rows > row)
849
// Remove rows to new size.
851
resize_rows(row-1, cur_cols, col);
855
assert(cur_rows == row);
856
resize_rows(cur_rows-1, cur_cols, col);
872
typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
873
for (; itr_row != itr_row_end; ++itr_row)
875
typename row_type::const_iterator itr_col = itr_row->begin(), itr_col_end = itr_row->end();
876
for (; itr_col != itr_col_end; ++itr_col)
878
matrix_element_t elem_type = itr_col->m_type;
879
if (elem_type != element_numeric && elem_type != element_boolean)
895
return m_rows.empty();
898
::mdds::storage_base<matrix_type>* clone() const
900
return new storage_filled(*this);
903
const rows_type& get_rows() const { return m_rows; }
908
* Resize rows to a new column size, from row 0 up to specified upper
911
void resize_rows(size_t upper_row, size_t cur_cols, size_t new_cols)
913
for (size_t i = 0; i <= upper_row; ++i)
915
// Resize pre-existing rows to new column size.
916
if (new_cols > cur_cols)
918
size_t new_col_count = new_cols - cur_cols;
919
for (size_t j = 0; j < new_col_count; ++j)
920
insert_new_elem(m_rows[i]);
922
else if (new_cols < cur_cols)
923
m_rows[i].resize(new_cols);
927
void init_row(row_type& row, size_t col_size)
929
row.reserve(col_size);
930
for (size_t j = 0; j < col_size; ++j)
931
insert_new_elem(row);
934
void insert_new_elem(row_type& row)
936
matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
939
case matrix_init_element_zero:
940
row.push_back(new element(static_cast<double>(0.0)));
942
case matrix_init_element_empty:
943
row.push_back(new element);
946
throw matrix_storage_error("unknown init type.");
957
* This storage stores only non-empty elements.
959
template<typename _MatrixType>
960
class storage_sparse : public storage_base<_MatrixType>
962
typedef _MatrixType matrix_type;
964
typedef typename matrix_type::string_type string_type;
967
typedef typename matrix_type::element element;
968
typedef ::boost::ptr_map<size_t, element> row_type;
969
typedef ::boost::ptr_map<size_t, row_type> rows_type;
972
const element& operator() (const typename row_type::const_iterator& itr) const
979
const row_type& operator() (const typename rows_type::const_iterator& itr) const
984
typedef ::mdds::const_itr_access<storage_sparse, elem_wrap, rows_wrap> const_itr_access;
986
storage_sparse(size_t _rows, size_t _cols, matrix_init_element_t init_type) :
987
storage_base<matrix_type>(matrix_storage_sparse, init_type),
988
m_row_size(_rows), m_col_size(_cols),
989
m_numeric(_rows && _cols), m_valid(true)
991
switch (storage_base<matrix_type>::get_init_type())
993
case matrix_init_element_zero:
994
m_empty_elem.m_type = element_numeric;
995
m_empty_elem.m_numeric = 0.0;
998
m_empty_elem.m_type = element_empty;
1003
storage_sparse(const storage_sparse& r) :
1004
storage_base<matrix_type>(r),
1006
m_empty_elem(r.m_empty_elem),
1007
m_row_size(r.m_row_size),
1008
m_col_size(r.m_col_size) {}
1010
virtual ~storage_sparse() {}
1012
const_itr_access* get_const_itr_access() const { return new const_itr_access(*this); }
1014
element & get_element(size_t row, size_t col)
1016
if (row >= m_row_size || col >= m_col_size)
1017
throw matrix_storage_error("specified element is out-of-bound.");
1021
typename rows_type::iterator itr = m_rows.find(row);
1022
if (itr == m_rows.end())
1024
// Insert a brand-new row.
1025
::std::pair<typename rows_type::iterator, bool> r = m_rows.insert(row, new row_type);
1027
throw matrix_storage_error("failed to insert a new row instance into storage_sparse.");
1031
row_type& row_store = *itr->second;
1032
typename row_type::iterator itr_elem = row_store.find(col);
1033
if (itr_elem == row_store.end())
1035
// Insert a new element at this column position.
1036
::std::pair<typename row_type::iterator, bool> r = row_store.insert(col, new element);
1038
throw matrix_storage_error("failed to insert a new element instance.");
1041
return *itr_elem->second;
1044
matrix_element_t get_type(size_t row, size_t col) const
1046
typename rows_type::const_iterator itr = m_rows.find(row);
1047
if (itr == m_rows.end())
1048
return m_empty_elem.m_type;
1050
const row_type& row_store = *itr->second;
1051
typename row_type::const_iterator itr_elem = row_store.find(col);
1052
if (itr_elem == row_store.end())
1053
return m_empty_elem.m_type;
1055
return itr_elem->second->m_type;
1058
double get_numeric(size_t row, size_t col) const
1060
const element& elem = get_non_empty_element(row, col);
1061
switch (elem.m_type)
1063
case element_numeric:
1064
return elem.m_numeric;
1065
case element_boolean:
1066
return static_cast<double>(elem.m_boolean);
1074
const string_type* get_string(size_t row, size_t col) const
1076
matrix_element_t elem_type = get_type(row, col);
1077
if (elem_type != element_string)
1078
throw matrix_storage_error("element type is not string.");
1080
return get_non_empty_element(row, col).mp_string;
1083
bool get_boolean(size_t row, size_t col) const
1085
matrix_element_t elem_type = get_type(row, col);
1086
if (elem_type != element_boolean)
1087
throw matrix_storage_error("element type is not string.");
1089
return get_non_empty_element(row, col).m_boolean;
1102
typedef ::std::pair<size_t, size_t> elem_pos_type;
1104
struct elem_pos_sorter : public ::std::binary_function<elem_pos_type, elem_pos_type, bool>
1106
bool operator() (const elem_pos_type& left, const elem_pos_type& right) const
1108
if (left.first != right.first)
1109
return left.first < right.first;
1110
return left.second < right.second;
1116
using namespace std;
1120
// First, pick up the positions of all non-empty elements.
1121
vector<elem_pos_type> filled_elems;
1123
typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
1124
for (; itr_row != itr_row_end; ++itr_row)
1126
size_t row_idx = itr_row->first;
1127
const row_type& row = *itr_row->second;
1128
typename row_type::const_iterator itr_col = row.begin(), itr_col_end = row.end();
1129
for (; itr_col != itr_col_end; ++itr_col)
1131
// Be sure to swap the row and column indices.
1132
filled_elems.push_back(elem_pos_type(itr_col->first, row_idx));
1136
// Sort by row index first, then by column index.
1137
sort(filled_elems.begin(), filled_elems.end(), elem_pos_sorter());
1139
// Iterate through the non-empty element positions and perform
1141
typename vector<elem_pos_type>::const_iterator
1142
itr_pos = filled_elems.begin(), itr_pos_end = filled_elems.end();
1143
while (itr_pos != itr_pos_end)
1145
// First item of the new row.
1146
size_t row_idx = itr_pos->first;
1147
size_t col_idx = itr_pos->second;
1148
pair<typename rows_type::iterator, bool> r = trans.insert(row_idx, new row_type);
1150
throw matrix_storage_error("failed to insert a new row instance during transposition.");
1152
typename rows_type::iterator itr_row = r.first;
1153
row_type& row = *itr_row->second;
1154
pair<typename row_type::iterator, bool> r2 =
1155
row.insert(col_idx, new element(m_rows[col_idx][row_idx]));
1157
throw matrix_storage_error("afiled to insert a new element instance during transposition.");
1159
// Keep iterating until we get a different row index.
1160
for (++itr_pos; itr_pos != itr_pos_end && itr_pos->first == row_idx; ++itr_pos)
1162
col_idx = itr_pos->second;
1163
r2 = row.insert(col_idx, new element(m_rows[col_idx][row_idx]));
1165
throw matrix_storage_error("afiled to insert a new element instance during transposition.");
1170
::std::swap(m_row_size, m_col_size);
1173
void resize(size_t row, size_t col)
1183
// Resizing a sparse matrix need to modify the data only when
1186
if (m_row_size > row)
1188
// Remove all rows where the row index is greater than or
1190
typename rows_type::iterator itr = m_rows.lower_bound(row);
1191
m_rows.erase(itr, m_rows.end());
1194
if (m_col_size > col)
1196
typename rows_type::iterator itr = m_rows.begin(), itr_end = m_rows.end();
1197
for (; itr != itr_end; ++itr)
1199
// Now, remove all columns where the column index is
1200
// greater than or equal to 'col'.
1201
row_type& row_container = *itr->second;
1202
typename row_type::iterator itr_elem = row_container.lower_bound(col);
1203
row_container.erase(itr_elem, row_container.end());
1222
using namespace std;
1227
size_t non_empty_count = 0;
1228
typename rows_type::const_iterator itr_row = m_rows.begin(), itr_row_end = m_rows.end();
1229
for (; itr_row != itr_row_end; ++itr_row)
1231
const row_type& row = *itr_row->second;
1232
non_empty_count += row.size();
1233
assert(row.size() <= m_col_size);
1234
typename row_type::const_iterator itr_col = row.begin(), itr_col_end = row.end();
1235
for (; itr_col != itr_col_end; ++itr_col)
1237
const element& elem = *itr_col->second;
1238
if (elem.m_type != element_numeric && elem.m_type != element_boolean)
1247
// All non-empty elements are numeric.
1249
matrix_init_element_t init_type = storage_base<matrix_type>::get_init_type();
1250
if (init_type == matrix_init_element_zero)
1254
size_t total_elem_count = m_row_size * m_col_size;
1255
assert(non_empty_count <= total_elem_count);
1256
m_numeric = total_elem_count == non_empty_count;
1265
// If one of row and column sizes are zero, the other size must be
1266
// zero, and vise versa.
1267
assert((!m_row_size && !m_col_size) || (m_row_size && m_col_size));
1269
return m_row_size == 0 || m_col_size == 0;
1272
storage_base<matrix_type>* clone() const
1274
return new storage_sparse(*this);
1277
const rows_type& get_rows() const { return m_rows; }
1280
const element& get_non_empty_element(size_t row, size_t col) const
1282
typename rows_type::const_iterator itr = m_rows.find(row);
1283
if (itr == m_rows.end())
1284
return m_empty_elem;
1286
const row_type& row_store = *itr->second;
1287
typename row_type::const_iterator itr_elem = row_store.find(col);
1288
if (itr_elem == row_store.end())
1289
return m_empty_elem;
1290
return *itr_elem->second;
1295
element m_empty_elem;