GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
boolSparse.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2013 David Bateman
4 Copyright (C) 1998-2004 Andy Adler
5 Copyright (C) 2010 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <iostream>
30 #include <vector>
31 
32 #include "quit.h"
33 #include "lo-ieee.h"
34 #include "lo-mappers.h"
35 
36 #include "boolSparse.h"
37 #include "dSparse.h"
38 #include "oct-mem.h"
39 #include "oct-locbuf.h"
40 
41 // SparseBoolMatrix class.
42 
43 bool
45 {
46  octave_idx_type nr = rows ();
47  octave_idx_type nc = cols ();
48  octave_idx_type nz = nnz ();
49  octave_idx_type nr_a = a.rows ();
50  octave_idx_type nc_a = a.cols ();
51  octave_idx_type nz_a = a.nnz ();
52 
53  if (nr != nr_a || nc != nc_a || nz != nz_a)
54  return false;
55 
56  for (octave_idx_type i = 0; i < nc + 1; i++)
57  if (cidx (i) != a.cidx (i))
58  return false;
59 
60  for (octave_idx_type i = 0; i < nz; i++)
61  if (data (i) != a.data (i) || ridx (i) != a.ridx (i))
62  return false;
63 
64  return true;
65 }
66 
67 bool
69 {
70  return !(*this == a);
71 }
72 
76 {
77  Sparse<bool>::insert (a, r, c);
78  return *this;
79 }
80 
83  const Array<octave_idx_type>& indx)
84 {
85  Sparse<bool>::insert (a, indx);
86  return *this;
87 }
88 
91  const Array<octave_idx_type>& ra_idx)
92 {
93  // Don't use numel to avoid all possiblity of an overflow
94  if (rb.rows () > 0 && rb.cols () > 0)
95  insert (rb, ra_idx(0), ra_idx(1));
96  return *this;
97 }
98 
99 // unary operations
100 
103 {
104  octave_idx_type nr = rows ();
105  octave_idx_type nc = cols ();
106  octave_idx_type nz1 = nnz ();
107  octave_idx_type nz2 = nr*nc - nz1;
108 
109  SparseBoolMatrix r (nr, nc, nz2);
110 
111  octave_idx_type ii = 0;
112  octave_idx_type jj = 0;
113  r.cidx (0) = 0;
114  for (octave_idx_type i = 0; i < nc; i++)
115  {
116  for (octave_idx_type j = 0; j < nr; j++)
117  {
118  if (jj < cidx (i+1) && ridx (jj) == j)
119  jj++;
120  else
121  {
122  r.data (ii) = true;
123  r.ridx (ii++) = j;
124  }
125  }
126  r.cidx (i+1) = ii;
127  }
128 
129  return r;
130 }
131 
132 // other operations
133 
134 // FIXME: Do these really belong here? Maybe they should be in a base class?
135 
137 SparseBoolMatrix::all (int dim) const
138 {
139  SPARSE_ALL_OP (dim);
140 }
141 
143 SparseBoolMatrix::any (int dim) const
144 {
145  Sparse<bool> retval;
146  octave_idx_type nr = rows (), nc = cols (), nz = nnz ();
147  if (dim == -1)
148  dim = (nr == 1 && nc != 1) ? 1 : 0;
149 
150  if (dim == 0)
151  {
152  // Result is a row vector.
153  retval = Sparse<bool> (1, nc);
154  retval.xcidx (0) = 0;
155  for (octave_idx_type i = 0; i < nc; i++)
156  retval.xcidx (i+1) = retval.xcidx (i) + (cidx (i+1) > cidx (i));
157  octave_idx_type new_nz = retval.xcidx (nc);
158  retval.change_capacity (new_nz);
159  fill_or_memset (new_nz, static_cast<octave_idx_type> (0), retval.ridx ());
160  fill_or_memset (new_nz, true, retval.data ());
161  }
162  else if (dim == 1)
163  {
164  // Result is a column vector.
165  if (nz > nr/4)
166  {
167  // We can use O(nr) memory.
168  Array<bool> tmp (dim_vector (nr, 1), false);
169  for (octave_idx_type i = 0; i < nz; i++)
170  tmp.xelem (ridx (i)) = true;
171  retval = tmp;
172  }
173  else
174  {
175  Array<octave_idx_type> tmp (dim_vector (nz, 1));
176  copy_or_memcpy (nz, ridx (), tmp.fortran_vec ());
177  retval = Sparse<bool> (Array<bool> (dim_vector (1, 1), true),
178  idx_vector (tmp),
179  idx_vector (static_cast<octave_idx_type> (0)),
180  nr, 1, false);
181  }
182  }
183 
184  return retval;
185 }
186 
188 SparseBoolMatrix::sum (int dim) const
189 {
190  Sparse<double> retval;
191  octave_idx_type nr = rows (), nc = cols (), nz = nnz ();
192  if (dim == -1)
193  dim = (nr == 1 && nc != 1) ? 1 : 0;
194 
195  if (dim == 0)
196  {
197  // Result is a row vector.
198  retval = Sparse<double> (1, nc);
199  for (octave_idx_type i = 0; i < nc; i++)
200  retval.xcidx (i+1) = retval.xcidx (i) + (cidx (i+1) > cidx (i));
201  octave_idx_type new_nz = retval.xcidx (nc);
202  retval.change_capacity (new_nz);
203  fill_or_memset (new_nz, static_cast<octave_idx_type> (0), retval.ridx ());
204  for (octave_idx_type i = 0, k = 0; i < nc; i++)
205  {
206  octave_idx_type c = cidx (i+1) - cidx (i);
207  if (c > 0)
208  retval.xdata (k++) = c;
209  }
210  }
211  else if (dim == 1)
212  {
213  // Result is a column vector.
214  if (nz > nr)
215  {
216  // We can use O(nr) memory.
217  Array<double> tmp (dim_vector (nr, 1), 0);
218  for (octave_idx_type i = 0; i < nz; i++)
219  tmp.xelem (ridx (i)) += 1.0;
220  retval = tmp;
221  }
222  else
223  {
224  Array<octave_idx_type> tmp (dim_vector (nz, 1));
225  copy_or_memcpy (nz, ridx (), tmp.fortran_vec ());
226  retval = Sparse<double> (Array<double> (dim_vector (1, 1), 1.0),
227  idx_vector (tmp),
228  idx_vector (static_cast<octave_idx_type> (0)),
229  nr, 1);
230  }
231  }
232 
233  return retval;
234 }
235 
238 {
239  return Sparse<bool>::diag (k);
240 }
241 
244 {
245  octave_idx_type nr = rows ();
246  octave_idx_type nc = cols ();
247 
248  boolMatrix retval (nr, nc, false);
249  for (octave_idx_type j = 0; j < nc; j++)
250  for (octave_idx_type i = cidx (j); i < cidx (j+1); i++)
251  retval.elem (ridx (i), j) = data (i);
252 
253  return retval;
254 }
255 
256 std::ostream&
257 operator << (std::ostream& os, const SparseBoolMatrix& a)
258 {
259  octave_idx_type nc = a.cols ();
260 
261  // add one to the printed indices to go from
262  // zero-based to one-based arrays
263  for (octave_idx_type j = 0; j < nc; j++)
264  {
265  octave_quit ();
266  for (octave_idx_type i = a.cidx (j); i < a.cidx (j+1); i++)
267  os << a.ridx (i) + 1 << " " << j + 1 << " " << a.data (i) << "\n";
268  }
269 
270  return os;
271 }
272 
273 std::istream&
274 operator >> (std::istream& is, SparseBoolMatrix& a)
275 {
276  typedef SparseBoolMatrix::element_type elt_type;
277 
278  return read_sparse_matrix<elt_type> (is, a, octave_read_value<bool>);
279 }
280 
283 {
284  return Sparse<bool>::squeeze ();
285 }
286 
288 SparseBoolMatrix::index (const idx_vector& i, bool resize_ok) const
289 {
290  return Sparse<bool>::index (i, resize_ok);
291 }
292 
295  bool resize_ok) const
296 {
297  return Sparse<bool>::index (i, j, resize_ok);
298 }
299 
301 SparseBoolMatrix::reshape (const dim_vector& new_dims) const
302 {
303  return Sparse<bool>::reshape (new_dims);
304 }
305 
308 {
309  return Sparse<bool>::permute (vec, inv);
310 }
311 
314 {
315  return Sparse<bool>::ipermute (vec);
316 }
317 
318 SPARSE_SMS_EQNE_OPS (SparseBoolMatrix, false, , bool, false, )
320 
321 SPARSE_SSM_EQNE_OPS (bool, false, , SparseBoolMatrix, false, )
322 SPARSE_SSM_BOOL_OPS (bool, SparseBoolMatrix, false)
323 
324 SPARSE_SMSM_EQNE_OPS (SparseBoolMatrix, false, , SparseBoolMatrix, false, )
325 SPARSE_SMSM_BOOL_OPS (SparseBoolMatrix, SparseBoolMatrix, false)