1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17 
18 
19 //! \addtogroup glue_histc
20 //! @{
21 
22 
23 template<typename eT>
24 inline
25 void
apply_noalias(Mat<uword> & C,const Mat<eT> & A,const Mat<eT> & B,const uword dim)26 glue_histc::apply_noalias(Mat<uword>& C, const Mat<eT>& A, const Mat<eT>& B, const uword dim)
27   {
28   arma_extra_debug_sigprint();
29 
30   arma_debug_check( ((B.is_vec() == false) && (B.is_empty() == false)), "histc(): parameter 'edges' must be a vector" );
31 
32   const uword A_n_rows = A.n_rows;
33   const uword A_n_cols = A.n_cols;
34 
35   const uword B_n_elem = B.n_elem;
36 
37   if( B_n_elem == uword(0) )  { C.reset(); return; }
38 
39   arma_debug_check
40     (
41     ((Col<eT>(const_cast<eT*>(B.memptr()), B_n_elem, false, false)).is_sorted("strictascend") == false),
42     "hist(): given 'edges' vector does not contain monotonically increasing values"
43     );
44 
45   const eT*   B_mem       = B.memptr();
46   const uword B_n_elem_m1 = B_n_elem - 1;
47 
48   if(dim == uword(0))
49     {
50     C.zeros(B_n_elem, A_n_cols);
51 
52     for(uword col=0; col < A_n_cols; ++col)
53       {
54       const eT*    A_coldata = A.colptr(col);
55             uword* C_coldata = C.colptr(col);
56 
57       for(uword row=0; row < A_n_rows; ++row)
58         {
59         const eT x = A_coldata[row];
60 
61         for(uword i=0; i < B_n_elem_m1; ++i)
62           {
63                if( (B_mem[i]           <= x) && (x < B_mem[i+1]) )  { C_coldata[i]++;           break; }
64           else if(  B_mem[B_n_elem_m1] == x                      )  { C_coldata[B_n_elem_m1]++; break; }    // for compatibility with Matlab
65           }
66         }
67       }
68     }
69   else
70   if(dim == uword(1))
71     {
72     C.zeros(A_n_rows, B_n_elem);
73 
74     if(A.n_rows == 1)
75       {
76       const uword  A_n_elem = A.n_elem;
77       const eT*    A_mem    = A.memptr();
78             uword* C_mem    = C.memptr();
79 
80       for(uword j=0; j < A_n_elem; ++j)
81         {
82         const eT x = A_mem[j];
83 
84         for(uword i=0; i < B_n_elem_m1; ++i)
85           {
86                if( (B_mem[i]           <= x) && (x < B_mem[i+1]) )  { C_mem[i]++;           break; }
87           else if(  B_mem[B_n_elem_m1] == x                      )  { C_mem[B_n_elem_m1]++; break; }    // for compatibility with Matlab
88           }
89         }
90       }
91     else
92       {
93       for(uword row=0; row < A_n_rows; ++row)
94       for(uword col=0; col < A_n_cols; ++col)
95         {
96         const eT x = A.at(row,col);
97 
98         for(uword i=0; i < B_n_elem_m1; ++i)
99           {
100                if( (B_mem[i]            <= x) && (x < B_mem[i+1]) )  { C.at(row,i)++;           break; }
101           else if(  B_mem[B_n_elem_m1]  == x                      )  { C.at(row,B_n_elem_m1)++; break; }   // for compatibility with Matlab
102           }
103         }
104       }
105     }
106   }
107 
108 
109 
110 template<typename T1, typename T2>
111 inline
112 void
apply(Mat<uword> & C,const mtGlue<uword,T1,T2,glue_histc> & expr)113 glue_histc::apply(Mat<uword>& C, const mtGlue<uword,T1,T2,glue_histc>& expr)
114   {
115   arma_extra_debug_sigprint();
116 
117   const uword dim = expr.aux_uword;
118 
119   arma_debug_check( (dim > 1), "histc(): parameter 'dim' must be 0 or 1" );
120 
121   const quasi_unwrap<T1> UA(expr.A);
122   const quasi_unwrap<T2> UB(expr.B);
123 
124   if(UA.is_alias(C) || UB.is_alias(C))
125     {
126     Mat<uword> tmp;
127 
128     glue_histc::apply_noalias(tmp, UA.M, UB.M, dim);
129 
130     C.steal_mem(tmp);
131     }
132   else
133     {
134     glue_histc::apply_noalias(C, UA.M, UB.M, dim);
135     }
136   }
137 
138 
139 
140 template<typename T1, typename T2>
141 inline
142 void
apply(Mat<uword> & C,const mtGlue<uword,T1,T2,glue_histc_default> & expr)143 glue_histc_default::apply(Mat<uword>& C, const mtGlue<uword,T1,T2,glue_histc_default>& expr)
144   {
145   arma_extra_debug_sigprint();
146 
147   const quasi_unwrap<T1> UA(expr.A);
148   const quasi_unwrap<T2> UB(expr.B);
149 
150   const uword dim = (T1::is_xvec) ? uword(UA.M.is_rowvec() ? 1 : 0) : uword((T1::is_row) ? 1 : 0);
151 
152   if(UA.is_alias(C) || UB.is_alias(C))
153     {
154     Mat<uword> tmp;
155 
156     glue_histc::apply_noalias(tmp, UA.M, UB.M, dim);
157 
158     C.steal_mem(tmp);
159     }
160   else
161     {
162     glue_histc::apply_noalias(C, UA.M, UB.M, dim);
163     }
164   }
165 
166 
167 //! @}
168