Chris@49
|
1 // Copyright (C) 2012 Ryan Curtin
|
Chris@49
|
2 // Copyright (C) 2012 Conrad Sanderson
|
Chris@49
|
3 //
|
Chris@49
|
4 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
7
|
Chris@49
|
8
|
Chris@49
|
9 //! \addtogroup fn_n_unique
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12
|
Chris@49
|
13 //! \brief
|
Chris@49
|
14 //! Get the number of unique nonzero elements in two sparse matrices.
|
Chris@49
|
15 //! This is very useful for determining the amount of memory necessary before
|
Chris@49
|
16 //! a sparse matrix operation on two matrices.
|
Chris@49
|
17
|
Chris@49
|
18 template<typename T1, typename T2, typename op_n_unique_type>
|
Chris@49
|
19 inline
|
Chris@49
|
20 uword
|
Chris@49
|
21 n_unique
|
Chris@49
|
22 (
|
Chris@49
|
23 const SpBase<typename T1::elem_type, T1>& x,
|
Chris@49
|
24 const SpBase<typename T2::elem_type, T2>& y,
|
Chris@49
|
25 const op_n_unique_type junk
|
Chris@49
|
26 )
|
Chris@49
|
27 {
|
Chris@49
|
28 arma_extra_debug_sigprint();
|
Chris@49
|
29
|
Chris@49
|
30 const SpProxy<T1> pa(x.get_ref());
|
Chris@49
|
31 const SpProxy<T2> pb(y.get_ref());
|
Chris@49
|
32
|
Chris@49
|
33 return n_unique(pa,pb,junk);
|
Chris@49
|
34 }
|
Chris@49
|
35
|
Chris@49
|
36
|
Chris@49
|
37
|
Chris@49
|
38 template<typename T1, typename T2, typename op_n_unique_type>
|
Chris@49
|
39 arma_hot
|
Chris@49
|
40 inline
|
Chris@49
|
41 uword
|
Chris@49
|
42 n_unique
|
Chris@49
|
43 (
|
Chris@49
|
44 const SpProxy<T1>& pa,
|
Chris@49
|
45 const SpProxy<T2>& pb,
|
Chris@49
|
46 const op_n_unique_type junk
|
Chris@49
|
47 )
|
Chris@49
|
48 {
|
Chris@49
|
49 arma_extra_debug_sigprint();
|
Chris@49
|
50 arma_ignore(junk);
|
Chris@49
|
51
|
Chris@49
|
52 // Use iterators.
|
Chris@49
|
53 typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
|
Chris@49
|
54 typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
|
Chris@49
|
55
|
Chris@49
|
56 uword total_n_nonzero = 0;
|
Chris@49
|
57
|
Chris@49
|
58 while((x_it != pa.end()) || (y_it != pb.end()))
|
Chris@49
|
59 {
|
Chris@49
|
60 if(x_it == y_it)
|
Chris@49
|
61 {
|
Chris@49
|
62 if(op_n_unique_type::eval((*x_it), (*y_it)) != typename T1::elem_type(0))
|
Chris@49
|
63 {
|
Chris@49
|
64 ++total_n_nonzero;
|
Chris@49
|
65 }
|
Chris@49
|
66
|
Chris@49
|
67 ++x_it;
|
Chris@49
|
68 ++y_it;
|
Chris@49
|
69 }
|
Chris@49
|
70 else
|
Chris@49
|
71 {
|
Chris@49
|
72 if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.row() < y_it.row()))) // if y is closer to the end
|
Chris@49
|
73 {
|
Chris@49
|
74 if(op_n_unique_type::eval((*x_it), typename T1::elem_type(0)) != typename T1::elem_type(0))
|
Chris@49
|
75 {
|
Chris@49
|
76 ++total_n_nonzero;
|
Chris@49
|
77 }
|
Chris@49
|
78
|
Chris@49
|
79 ++x_it;
|
Chris@49
|
80 }
|
Chris@49
|
81 else // x is closer to the end
|
Chris@49
|
82 {
|
Chris@49
|
83 if(op_n_unique_type::eval(typename T1::elem_type(0), (*y_it)) != typename T1::elem_type(0))
|
Chris@49
|
84 {
|
Chris@49
|
85 ++total_n_nonzero;
|
Chris@49
|
86 }
|
Chris@49
|
87
|
Chris@49
|
88 ++y_it;
|
Chris@49
|
89 }
|
Chris@49
|
90 }
|
Chris@49
|
91 }
|
Chris@49
|
92
|
Chris@49
|
93 return total_n_nonzero;
|
Chris@49
|
94 }
|
Chris@49
|
95
|
Chris@49
|
96
|
Chris@49
|
97 // Simple operators.
|
Chris@49
|
98 struct op_n_unique_add
|
Chris@49
|
99 {
|
Chris@49
|
100 template<typename eT> inline static eT eval(const eT& l, const eT& r) { return (l + r); }
|
Chris@49
|
101 };
|
Chris@49
|
102
|
Chris@49
|
103 struct op_n_unique_sub
|
Chris@49
|
104 {
|
Chris@49
|
105 template<typename eT> inline static eT eval(const eT& l, const eT& r) { return (l - r); }
|
Chris@49
|
106 };
|
Chris@49
|
107
|
Chris@49
|
108 struct op_n_unique_mul
|
Chris@49
|
109 {
|
Chris@49
|
110 template<typename eT> inline static eT eval(const eT& l, const eT& r) { return (l * r); }
|
Chris@49
|
111 };
|
Chris@49
|
112
|
Chris@49
|
113 struct op_n_unique_count
|
Chris@49
|
114 {
|
Chris@49
|
115 template<typename eT> inline static eT eval(const eT& l, const eT& r) { return 1; }
|
Chris@49
|
116 };
|
Chris@49
|
117
|
Chris@49
|
118
|
Chris@49
|
119
|
Chris@49
|
120 //! @}
|