00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION)
00024 #pragma implementation
00025 #endif
00026
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030
00031 #include <cstdlib>
00032
00033 #include <iostream>
00034
00035 #include "Range.h"
00036 #include "boolNDArray.h"
00037 #include "dColVector.h"
00038 #include "dNDArray.h"
00039
00040 #include "idx-vector.h"
00041 #include "lo-error.h"
00042 #include "lo-mappers.h"
00043
00044 #define IDX_VEC_REP idx_vector::idx_vector_rep
00045
00046 IDX_VEC_REP::idx_vector_rep (const IDX_VEC_REP& a)
00047 : data (0), len (a.len), num_zeros (a.num_zeros), num_ones (a.num_ones),
00048 max_val (a.max_val), min_val (a.min_val),
00049 frozen_at_z_len (a.frozen_at_z_len), frozen_len (a.frozen_len),
00050 colon (a.colon), one_zero (a.one_zero), initialized (a.initialized),
00051 frozen (a.frozen), colon_equiv_checked (a.colon_equiv_checked),
00052 colon_equiv (a.colon_equiv), orig_dims (a.orig_dims)
00053 {
00054 if (len > 0)
00055 {
00056 data = new int [len];
00057 for (int i = 0; i < len; i++)
00058 data[i] = a.data[i];
00059 }
00060 }
00061
00062 int
00063 IDX_VEC_REP::tree_to_mat_idx (double x, bool& conversion_error)
00064 {
00065 int retval = -1;
00066
00067 conversion_error = false;
00068
00069 if (D_NINT (x) != x)
00070 {
00071 (*current_liboctave_error_handler)
00072 ("expecting integer index, found %f", x);
00073
00074 conversion_error = true;
00075 }
00076 else
00077 retval = static_cast<int> (x - 1);
00078
00079 return retval;
00080 }
00081
00082 static inline bool
00083 idx_is_inf_or_nan (double x)
00084 {
00085 bool retval = false;
00086
00087 if (xisnan (x))
00088 {
00089 (*current_liboctave_error_handler) ("NaN invalid as index");
00090 retval = true;
00091 }
00092 else if (xisinf (x))
00093 {
00094 (*current_liboctave_error_handler) ("Inf invalid as index");
00095 retval = true;
00096 }
00097
00098 return retval;
00099 }
00100
00101 IDX_VEC_REP::idx_vector_rep (const ColumnVector& v)
00102 : data (0), len (v.length ()), num_zeros (0), num_ones (0), max_val (0),
00103 min_val (0), count (1), frozen_at_z_len (0), frozen_len (0),
00104 colon (0), one_zero (0), initialized (0), frozen (0),
00105 colon_equiv_checked (0), colon_equiv (0), orig_dims (len, 1)
00106 {
00107 if (len == 0)
00108 {
00109 initialized = 1;
00110 return;
00111 }
00112 else
00113 {
00114 data = new int [len];
00115
00116 bool conversion_error = false;
00117
00118 for (int i = 0; i < len; i++)
00119 {
00120 double d = v.elem (i);
00121
00122 if (idx_is_inf_or_nan (d))
00123 return;
00124 else
00125 data[i] = tree_to_mat_idx (d, conversion_error);
00126
00127 if (conversion_error)
00128 return;
00129 }
00130 }
00131
00132 init_state ();
00133 }
00134
00135 IDX_VEC_REP::idx_vector_rep (const NDArray& nda)
00136 : data (0), len (nda.length ()), num_zeros (0), num_ones (0),
00137 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00138 frozen_len (0), colon (0), one_zero (0), initialized (0),
00139 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00140 orig_dims (nda.dims ())
00141 {
00142 if (len == 0)
00143 {
00144 initialized = 1;
00145 return;
00146 }
00147 else
00148 {
00149 int k = 0;
00150 data = new int [len];
00151
00152 bool conversion_error = false;
00153
00154 for (int i = 0; i < len; i++)
00155 {
00156 double d = nda.elem (i);
00157
00158 if (idx_is_inf_or_nan (d))
00159 return;
00160 else
00161 data[k++] = tree_to_mat_idx (d, conversion_error);
00162
00163 if (conversion_error)
00164 return;
00165 }
00166 }
00167
00168 init_state ();
00169 }
00170
00171 IDX_VEC_REP::idx_vector_rep (const Range& r)
00172 : data (0), len (r.nelem ()), num_zeros (0), num_ones (0),
00173 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00174 frozen_len (0), colon (0), one_zero (0), initialized (0),
00175 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00176 orig_dims (1, len)
00177 {
00178 if (len < 0)
00179 {
00180 (*current_liboctave_error_handler) ("invalid range used as index");
00181 return;
00182 }
00183 else if (len == 0)
00184 {
00185 initialized = 1;
00186 return;
00187 }
00188
00189 double b = r.base ();
00190 double step = r.inc ();
00191
00192 data = new int [len];
00193
00194 bool conversion_error = false;
00195
00196 for (int i = 0; i < len; i++)
00197 {
00198 double val = b + i * step;
00199
00200 if (idx_is_inf_or_nan (val))
00201 return;
00202 else
00203 data[i] = tree_to_mat_idx (val, conversion_error);
00204
00205 if (conversion_error)
00206 return;
00207 }
00208
00209 init_state ();
00210 }
00211
00212 IDX_VEC_REP::idx_vector_rep (double d)
00213 : data (0), len (1), num_zeros (0), num_ones (0),
00214 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00215 frozen_len (0), colon (0), one_zero (0), initialized (0),
00216 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00217 orig_dims (1, 1)
00218 {
00219 if (idx_is_inf_or_nan (d))
00220 return;
00221 else
00222 {
00223 data = new int [len];
00224
00225 bool conversion_error = false;
00226
00227 data[0] = tree_to_mat_idx (d, conversion_error);
00228
00229 if (conversion_error)
00230 return;
00231 }
00232
00233 init_state ();
00234 }
00235
00236 IDX_VEC_REP::idx_vector_rep (int i)
00237 : data (0), len (1), num_zeros (0), num_ones (0),
00238 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00239 frozen_len (0), colon (0), one_zero (0), initialized (0),
00240 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00241 orig_dims (1, 1)
00242 {
00243 data = new int [len];
00244
00245 data[0] = tree_to_mat_idx (i);
00246
00247 init_state ();
00248 }
00249
00250 IDX_VEC_REP::idx_vector_rep (char c)
00251 : data (0), len (0), num_zeros (0), num_ones (0),
00252 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00253 frozen_len (0), colon (1), one_zero (0), initialized (0),
00254 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00255 orig_dims (0, 0)
00256 {
00257 assert (c == ':');
00258
00259 init_state ();
00260 }
00261
00262 IDX_VEC_REP::idx_vector_rep (bool b)
00263 : data (0), len (1), num_zeros (0), num_ones (0),
00264 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00265 frozen_len (0), colon (0), one_zero (1), initialized (0),
00266 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00267 orig_dims (1, 1)
00268 {
00269 data = new int [len];
00270
00271 data[0] = tree_to_mat_idx (b);
00272
00273 init_state ();
00274 }
00275
00276 IDX_VEC_REP::idx_vector_rep (const boolNDArray& bnda)
00277 : data (0), len (bnda.length ()), num_zeros (0), num_ones (0),
00278 max_val (0), min_val (0), count (1), frozen_at_z_len (0),
00279 frozen_len (0), colon (0), one_zero (1), initialized (0),
00280 frozen (0), colon_equiv_checked (0), colon_equiv (0),
00281 orig_dims (bnda.dims ())
00282 {
00283 if (len == 0)
00284 {
00285 initialized = 1;
00286 return;
00287 }
00288 else
00289 {
00290 int k = 0;
00291 data = new int [len];
00292
00293 for (int i = 0; i < len; i++)
00294 data[k++] = tree_to_mat_idx (bnda.elem (i));
00295 }
00296
00297 init_state ();
00298 }
00299
00300 IDX_VEC_REP&
00301 IDX_VEC_REP::operator = (const IDX_VEC_REP& a)
00302 {
00303 if (this != &a)
00304 {
00305 delete [] data;
00306 len = a.len;
00307 data = new int [len];
00308 for (int i = 0; i < len; i++)
00309 data[i] = a.data[i];
00310
00311 num_zeros = a.num_zeros;
00312 num_ones = a.num_ones;
00313 max_val = a.max_val;
00314 min_val = a.min_val;
00315 frozen_at_z_len = a.frozen_at_z_len;
00316 frozen_len = a.frozen_len;
00317 colon = a.colon;
00318 one_zero = a.one_zero;
00319 initialized = a.initialized;
00320 frozen = a.frozen;
00321 colon_equiv_checked = a.colon_equiv_checked;
00322 colon_equiv = a.colon_equiv;
00323 orig_dims = a.orig_dims;
00324 }
00325
00326 return *this;
00327 }
00328
00329 void
00330 IDX_VEC_REP::init_state (void)
00331 {
00332 num_zeros = 0;
00333 num_ones = 0;
00334
00335 if (colon)
00336 {
00337 min_val = 0;
00338 max_val = 0;
00339 }
00340 else
00341 {
00342 min_val = max_val = data[0];
00343
00344 int i = 0;
00345 do
00346 {
00347 if (data[i] == -1)
00348 num_zeros++;
00349 else if (data[i] == 0)
00350 num_ones++;
00351
00352 if (data[i] > max_val)
00353 max_val = data[i];
00354
00355 if (data[i] < min_val)
00356 min_val = data[i];
00357 }
00358 while (++i < len);
00359 }
00360
00361 initialized = 1;
00362 }
00363
00364 void
00365 IDX_VEC_REP::maybe_convert_one_zero_to_idx (int z_len)
00366 {
00367 if (one_zero && (z_len == len || z_len == 0))
00368 {
00369 if (num_ones == 0)
00370 {
00371 len = 0;
00372 max_val = 0;
00373 min_val = 0;
00374 delete [] data;
00375 data = 0;
00376 }
00377 else
00378 {
00379 assert (num_ones + num_zeros == len);
00380
00381 int *new_data = new int [num_ones];
00382 int k = 0;
00383 for (int i = 0; i < len; i++)
00384 if (data[i] == 0)
00385 new_data[k++] = i;
00386
00387 delete [] data;
00388 len = num_ones;
00389 data = new_data;
00390
00391 min_val = max_val = data[0];
00392
00393 int i = 0;
00394 do
00395 {
00396 if (data[i] > max_val)
00397 max_val = data[i];
00398
00399 if (data[i] < min_val)
00400 min_val = data[i];
00401 }
00402 while (++i < len);
00403 }
00404 }
00405 }
00406
00407 int
00408 IDX_VEC_REP::checkelem (int n) const
00409 {
00410 if (n < 0 || n >= len)
00411 {
00412 (*current_liboctave_error_handler) ("idx-vector: index out of range");
00413 return 0;
00414 }
00415
00416 return elem (n);
00417 }
00418
00419 static inline int
00420 intcmp (const void *ii, const void *jj)
00421 {
00422 return (*(static_cast<const int *> (ii)) - *(static_cast<const int *> (jj)));
00423 }
00424
00425 static inline void
00426 sort_data (int *d, int l)
00427 {
00428 qsort (d, l, sizeof (int), intcmp);
00429 }
00430
00431 static inline int
00432 make_uniq (int *d, int l)
00433 {
00434 if (l < 2)
00435 return l;
00436
00437 int k = 0;
00438 for (int ii = 1; ii < l; ii++)
00439 {
00440 if (d[ii] != d[k])
00441 {
00442 k++;
00443 d[k] = d[ii];
00444 }
00445 }
00446 return k+1;
00447 }
00448
00449 static inline int *
00450 copy_data (const int *d, int l)
00451 {
00452 int *new_data = new int [l];
00453
00454 for (int ii = 0; ii < l; ii++)
00455 new_data[ii] = d[ii];
00456
00457 return new_data;
00458 }
00459
00460 int
00461 IDX_VEC_REP::is_colon_equiv (int n, int sort_uniq)
00462 {
00463 if (! colon_equiv_checked)
00464 {
00465 if (colon)
00466 {
00467 colon_equiv = 1;
00468 }
00469 else if (len > 1)
00470 {
00471 if (one_zero)
00472 {
00473 colon_equiv = (len == n && ones_count () == n);
00474 }
00475 else if (sort_uniq)
00476 {
00477 int *tmp_data = copy_data (data, len);
00478
00479 sort_data (tmp_data, len);
00480
00481 int tmp_len = make_uniq (tmp_data, len);
00482
00483 colon_equiv = (tmp_len == n
00484 && tmp_data[0] == 0
00485 && tmp_data[tmp_len-1] == tmp_len - 1);
00486
00487 delete [] tmp_data;
00488 }
00489 else
00490 {
00491 if (len == n)
00492 {
00493 colon_equiv = 1;
00494
00495 for (int ii = 0; ii < n; ii++)
00496 if (data[ii] != ii)
00497 {
00498 colon_equiv = 0;
00499 break;
00500 }
00501 }
00502 }
00503 }
00504 else
00505 colon_equiv = (len == n && (n == 0 || (n == 1 && data[0] == 0)));
00506
00507 colon_equiv_checked = 1;
00508 }
00509
00510 return colon_equiv;
00511 }
00512
00513 void
00514 IDX_VEC_REP::sort (bool uniq)
00515 {
00516 if (len > 1)
00517 {
00518 sort_data (data, len);
00519
00520 if (uniq)
00521 len = make_uniq (data, len);
00522 }
00523 }
00524
00525 void
00526 IDX_VEC_REP::shorten (int n)
00527 {
00528 if (n > 0 && n <= len)
00529 len = n;
00530 else
00531 (*current_liboctave_error_handler)
00532 ("idx_vector::shorten: internal error!");
00533 }
00534
00535 std::ostream&
00536 IDX_VEC_REP::print (std::ostream& os) const
00537 {
00538 for (int ii = 0; ii < len; ii++)
00539 os << data[ii] << "\n";
00540 return os;
00541 }
00542
00543 int
00544 IDX_VEC_REP::freeze (int z_len, const char *tag, bool resize_ok,
00545 bool warn_resize)
00546 {
00547 if (frozen)
00548 return frozen_len;
00549
00550 frozen_len = -1;
00551
00552 if (colon)
00553 frozen_len = z_len;
00554 else
00555 {
00556 if (len == 0)
00557 frozen_len = 0;
00558 else
00559 {
00560 maybe_convert_one_zero_to_idx (z_len);
00561
00562 max_val = max ();
00563 min_val = min ();
00564
00565 if (min_val < 0)
00566 {
00567 if (tag)
00568 (*current_liboctave_error_handler)
00569 ("invalid %s index = %d", tag, min_val+1);
00570 else
00571 (*current_liboctave_error_handler)
00572 ("invalid index = %d", min_val+1);
00573
00574 initialized = 0;
00575 }
00576 else if (! resize_ok && max_val >= z_len)
00577 {
00578 if (tag)
00579 (*current_liboctave_error_handler)
00580 ("invalid %s index = %d", tag, max_val+1);
00581 else
00582 (*current_liboctave_error_handler)
00583 ("invalid index = %d", max_val+1);
00584
00585 initialized = 0;
00586 }
00587 else
00588 {
00589 if (warn_resize && max_val >= z_len)
00590 {
00591 if (tag)
00592 (*current_liboctave_error_handler)
00593 ("resizing object with %s index = %d out of bounds",
00594 tag, max_val+1);
00595 else
00596 (*current_liboctave_error_handler)
00597 ("resizing object with index = %d out of bounds",
00598 max_val+1);
00599 }
00600
00601 frozen_len = length (z_len);
00602 }
00603 }
00604 }
00605
00606 frozen = 1;
00607
00608 frozen_at_z_len = z_len ? z_len : len;
00609
00610 return frozen_len;
00611 }
00612
00613
00614
00615
00616
00617