00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "Array-util.h"
00029 #include "dim-vector.h"
00030 #include "lo-error.h"
00031 #include "oct-locbuf.h"
00032
00033 bool
00034 index_in_bounds (const Array<octave_idx_type>& ra_idx,
00035 const dim_vector& dimensions)
00036 {
00037 bool retval = true;
00038
00039 int n = ra_idx.length ();
00040
00041 if (n == dimensions.length ())
00042 {
00043 for (int i = 0; i < n; i++)
00044 {
00045 if (ra_idx(i) < 0 || ra_idx(i) >= dimensions(i))
00046 {
00047 retval = false;
00048 break;
00049 }
00050 }
00051 }
00052 else
00053 retval = false;
00054
00055 return retval;
00056 }
00057
00058 void
00059 increment_index (Array<octave_idx_type>& ra_idx, const dim_vector& dimensions,
00060 int start_dimension)
00061 {
00062 ra_idx(start_dimension)++;
00063
00064 int n = ra_idx.length () - 1;
00065 int nda = dimensions.length ();
00066
00067 for (int i = start_dimension; i < n; i++)
00068 {
00069 if (ra_idx(i) < (i < nda ? dimensions(i) : 1))
00070 break;
00071 else
00072 {
00073 ra_idx(i) = 0;
00074 ra_idx(i+1)++;
00075 }
00076 }
00077 }
00078
00079 octave_idx_type
00080 get_scalar_idx (Array<octave_idx_type>& idx, dim_vector& dims)
00081 {
00082 octave_idx_type retval (-1);
00083
00084 int n = idx.length ();
00085
00086 if (n > 0)
00087 {
00088 retval = idx(--n);
00089
00090 while (--n >= 0)
00091 {
00092 retval *= dims (n);
00093
00094 retval += idx(n);
00095 }
00096 }
00097 return retval;
00098 }
00099
00100 octave_idx_type
00101 num_ones (const Array<octave_idx_type>& ra_idx)
00102 {
00103 octave_idx_type retval = 0;
00104
00105 for (octave_idx_type i = 0; i < ra_idx.length (); i++)
00106 {
00107 if (ra_idx (i) == 1)
00108 retval++;
00109 }
00110
00111 return retval;
00112 }
00113
00114 bool
00115 is_scalar (const dim_vector& dim)
00116 {
00117 bool retval = true;
00118
00119 int n = dim.length ();
00120
00121 if (n == 0)
00122 {
00123 retval = false;
00124 }
00125 else
00126 {
00127 for (int i = 0; i < n; i ++)
00128 {
00129 if (dim (i) != 1)
00130 {
00131 retval = false;
00132
00133 break;
00134 }
00135 }
00136 }
00137 return retval;
00138 }
00139
00140 bool
00141 is_vector (const dim_vector& dim)
00142 {
00143 int m = 0;
00144 int n = dim.length ();
00145
00146 if (n == 0)
00147 m = 2;
00148 else
00149 {
00150 for (int i = 0; i < n; i ++)
00151 if (dim (i) > 1)
00152 m++;
00153 else if (dim(i) < 1)
00154 m += 2;
00155 }
00156
00157 return (m < 2);
00158 }
00159
00160 bool
00161 any_ones (const Array<octave_idx_type>& arr)
00162 {
00163 bool retval = false;
00164
00165 for (octave_idx_type i = 0; i < arr.length (); i++)
00166 {
00167 if (arr (i) == 1)
00168 {
00169 retval = true;
00170
00171 break;
00172 }
00173 }
00174 return retval;
00175 }
00176
00177 octave_idx_type
00178 compute_index (octave_idx_type n, const dim_vector& dims)
00179 {
00180 if (n < 0)
00181 gripe_invalid_index ();
00182 if (n >= dims.numel ())
00183 gripe_index_out_of_range (1, 1, n+1, dims.numel ());
00184
00185 return n;
00186 }
00187
00188 octave_idx_type
00189 compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims)
00190 {
00191 if (i < 0 || j < 0)
00192 gripe_invalid_index ();
00193 if (i >= dims(0))
00194 gripe_index_out_of_range (2, 1, i+1, dims(0));
00195 if (j >= dims.numel (1))
00196 gripe_index_out_of_range (2, 2, j+1, dims.numel (1));
00197
00198 return j*dims(0) + i;
00199 }
00200
00201 octave_idx_type
00202 compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,
00203 const dim_vector& dims)
00204 {
00205 if (i < 0 || j < 0 || k < 0)
00206 gripe_invalid_index ();
00207 if (i >= dims(0))
00208 gripe_index_out_of_range (3, 1, i+1, dims(0));
00209 if (j >= dims(1))
00210 gripe_index_out_of_range (3, 2, j+1, dims(1));
00211 if (k >= dims.numel (2))
00212 gripe_index_out_of_range (3, 3, k+1, dims.numel (2));
00213
00214 return (k*dims(1) + j)*dims(0) + i;
00215 }
00216
00217 octave_idx_type
00218 compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims)
00219 {
00220 int nd = ra_idx.length ();
00221 const dim_vector dv = dims.redim (nd);
00222 for (int d = 0; d < nd; d++)
00223 {
00224 if (ra_idx(d) < 0)
00225 gripe_invalid_index ();
00226 if (ra_idx(d) >= dv(d))
00227 gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
00228 }
00229
00230 return dv.compute_index (ra_idx.data ());
00231 }
00232
00233 Array<octave_idx_type>
00234 conv_to_int_array (const Array<idx_vector>& a)
00235 {
00236 Array<octave_idx_type> retval (a.dims ());
00237
00238 for (octave_idx_type i = 0; i < a.length (); i++)
00239 retval (i) = a(i).elem (0);
00240
00241 return retval;
00242 }
00243
00244 Array<idx_vector>
00245 conv_to_array (const idx_vector *tmp, const octave_idx_type len)
00246 {
00247 Array<idx_vector> retval (dim_vector (len, 1));
00248
00249 for (octave_idx_type i = 0; i < len; i++)
00250 retval (i) = tmp[i];
00251
00252 return retval;
00253 }
00254
00255 dim_vector
00256 freeze (Array<idx_vector>& ra_idx, const dim_vector& dimensions, int resize_ok)
00257 {
00258 dim_vector retval;
00259
00260 int n = ra_idx.length ();
00261
00262 assert (n == dimensions.length ());
00263
00264 retval.resize (n);
00265
00266 static const char *tag[3] = { "row", "column", 0 };
00267
00268 for (int i = 0; i < n; i++)
00269 retval(i) = ra_idx(i).freeze (dimensions(i), tag[i < 2 ? i : 3],
00270 resize_ok);
00271
00272 return retval;
00273 }
00274
00275 bool
00276 vector_equivalent (const dim_vector& dv)
00277 {
00278 int n = dv.length ();
00279
00280 bool found_first = false;
00281
00282 for (int i = 0; i < n; i++)
00283 {
00284 if (dv(i) != 1)
00285 {
00286 if (! found_first)
00287 found_first = true;
00288 else
00289 return false;
00290 }
00291 }
00292
00293 return true;
00294 }
00295
00296 bool
00297 all_ok (const Array<idx_vector>& ra_idx)
00298 {
00299 bool retval = true;
00300
00301 octave_idx_type n = ra_idx.length ();
00302
00303 for (octave_idx_type i = 0; i < n; i++)
00304 {
00305 if (! ra_idx(i))
00306 {
00307 retval = false;
00308 break;
00309 }
00310 }
00311
00312 return retval;
00313 }
00314
00315 bool
00316 any_orig_empty (const Array<idx_vector>& ra_idx)
00317 {
00318 bool retval = false;
00319
00320 octave_idx_type n = ra_idx.length ();
00321
00322 for (octave_idx_type i = 0; i < n; i++)
00323 {
00324 if (ra_idx(i).orig_empty ())
00325 {
00326 retval = true;
00327 break;
00328 }
00329 }
00330
00331 return retval;
00332 }
00333
00334 bool
00335 all_colon_equiv (const Array<idx_vector>& ra_idx,
00336 const dim_vector& frozen_lengths)
00337 {
00338 bool retval = true;
00339
00340 octave_idx_type idx_n = ra_idx.length ();
00341
00342 int n = frozen_lengths.length ();
00343
00344 assert (idx_n == n);
00345
00346 for (octave_idx_type i = 0; i < n; i++)
00347 {
00348 if (! ra_idx(i).is_colon_equiv (frozen_lengths(i)))
00349 {
00350 retval = false;
00351 break;
00352 }
00353 }
00354
00355 return retval;
00356 }
00357
00358 bool
00359 all_ones (const Array<octave_idx_type>& arr)
00360 {
00361 bool retval = true;
00362
00363 for (octave_idx_type i = 0; i < arr.length (); i++)
00364 {
00365 if (arr(i) != 1)
00366 {
00367 retval = false;
00368 break;
00369 }
00370 }
00371
00372 return retval;
00373 }
00374
00375 Array<octave_idx_type>
00376 get_elt_idx (const Array<idx_vector>& ra_idx,
00377 const Array<octave_idx_type>& result_idx)
00378 {
00379 octave_idx_type n = ra_idx.length ();
00380
00381 Array<octave_idx_type> retval (dim_vector (n, 1));
00382
00383 for (octave_idx_type i = 0; i < n; i++)
00384 retval(i) = ra_idx(i).elem (result_idx(i));
00385
00386 return retval;
00387 }
00388
00389 Array<octave_idx_type>
00390 get_ra_idx (octave_idx_type idx, const dim_vector& dims)
00391 {
00392 Array<octave_idx_type> retval;
00393
00394 int n_dims = dims.length ();
00395
00396 retval.resize (dim_vector (n_dims, 1));
00397
00398 for (int i = 0; i < n_dims; i++)
00399 retval(i) = 0;
00400
00401 assert (idx > 0 || idx < dims.numel ());
00402
00403 for (octave_idx_type i = 0; i < idx; i++)
00404 increment_index (retval, dims);
00405
00406
00407
00408
00409 #if 0
00410 octave_idx_type var = 1;
00411 for (int i = 0; i < n_dims; i++)
00412 {
00413 std::cout << "idx: " << idx << ", var: " << var
00414 << ", dims(" << i << "): " << dims(i) <<"\n";
00415 retval(i) = ((int)floor(((idx) / (double)var))) % dims(i);
00416 idx -= var * retval(i);
00417 var = dims(i);
00418 }
00419 #endif
00420
00421 return retval;
00422 }
00423
00424 dim_vector
00425 zero_dims_inquire (const Array<idx_vector>& ia, const dim_vector& rhdv)
00426 {
00427 int ial = ia.length (), rhdvl = rhdv.length ();
00428 dim_vector rdv = dim_vector::alloc (ial);
00429 bool *scalar = new bool[ial], *colon = new bool[ial];
00430
00431 int nonsc = 0;
00432 bool all_colons = true;
00433 for (int i = 0; i < ial; i++)
00434 {
00435
00436 scalar[i] = ia(i).is_scalar ();
00437 colon[i] = ia(i).is_colon ();
00438 if (! scalar[i]) nonsc++;
00439 if (! colon[i]) rdv(i) = ia(i).extent (0);
00440 all_colons = all_colons && colon[i];
00441 }
00442
00443
00444
00445 if (all_colons)
00446 {
00447 rdv = rhdv;
00448 rdv.resize(ial, 1);
00449 }
00450 else if (nonsc == rhdvl)
00451 {
00452 for (int i = 0, j = 0; i < ial; i++)
00453 {
00454 if (scalar[i]) continue;
00455 if (colon[i])
00456 rdv(i) = rhdv(j);
00457 j++;
00458 }
00459 }
00460 else
00461 {
00462 dim_vector rhdv0 = rhdv;
00463 rhdv0.chop_all_singletons ();
00464 int rhdv0l = rhdv0.length ();
00465 for (int i = 0, j = 0; i < ial; i++)
00466 {
00467 if (scalar[i]) continue;
00468 if (colon[i])
00469 rdv(i) = (j < rhdv0l) ? rhdv0(j++) : 1;
00470 }
00471 }
00472
00473 delete [] scalar;
00474 delete [] colon;
00475
00476 return rdv;
00477 }
00478
00479 dim_vector
00480 zero_dims_inquire (const idx_vector& i, const idx_vector& j,
00481 const dim_vector& rhdv)
00482 {
00483 bool icol = i.is_colon (), jcol = j.is_colon ();
00484 dim_vector rdv;
00485 if (icol && jcol && rhdv.length () == 2)
00486 {
00487 rdv(0) = rhdv(0);
00488 rdv(1) = rhdv(1);
00489 }
00490 else if (rhdv.length () == 2
00491 && ! i.is_scalar () && ! j.is_scalar ())
00492 {
00493 rdv(0) = icol ? rhdv(0) : i.extent (0);
00494 rdv(1) = jcol ? rhdv(1) : j.extent (0);
00495 }
00496 else
00497 {
00498 dim_vector rhdv0 = rhdv;
00499 rhdv0.chop_all_singletons ();
00500 int k = 0;
00501 rdv(0) = i.extent (0);
00502 if (icol)
00503 rdv(0) = rhdv0(k++);
00504 else if (! i.is_scalar ())
00505 k++;
00506 rdv(1) = j.extent (0);
00507 if (jcol)
00508 rdv(1) = rhdv0(k++);
00509 else if (! j.is_scalar ())
00510 k++;
00511 }
00512
00513 return rdv;
00514 }
00515
00516
00517 struct sub2ind_helper
00518 {
00519 octave_idx_type *ind, n;
00520
00521 sub2ind_helper (octave_idx_type *_ind, octave_idx_type _n)
00522 : ind(_ind), n(_n) { }
00523
00524 void operator ()(octave_idx_type k) { (*ind++ *= n) += k; }
00525 };
00526
00527 idx_vector
00528 sub2ind (const dim_vector& dv, const Array<idx_vector>& idxa)
00529 {
00530 idx_vector retval;
00531 octave_idx_type len = idxa.length ();
00532
00533 if (len >= 1)
00534 {
00535 const dim_vector dvx = dv.redim (len);
00536 bool all_ranges = true;
00537 octave_idx_type clen = -1;
00538
00539 for (octave_idx_type i = 0; i < len; i++)
00540 {
00541 idx_vector idx = idxa(i);
00542 octave_idx_type n = dvx(i);
00543
00544 all_ranges = all_ranges && idx.is_range ();
00545 if (clen < 0)
00546 clen = idx.length (n);
00547 else if (clen != idx.length (n))
00548 current_liboctave_error_handler ("sub2ind: lengths of indices must match");
00549
00550 if (idx.extent (n) > n)
00551 current_liboctave_error_handler ("sub2ind: index out of range");
00552 }
00553
00554 if (len == 1)
00555 retval = idxa(0);
00556 else if (clen == 1)
00557 {
00558
00559 octave_idx_type idx = idxa(len-1)(0);
00560 for (octave_idx_type i = len - 2; i >= 0; i--)
00561 idx = idx * dvx(i) + idxa(i)(0);
00562 retval = idx_vector (idx);
00563 }
00564 else if (all_ranges && clen != 0)
00565 {
00566
00567 octave_idx_type start = 0, step = 0;
00568 for (octave_idx_type i = len - 1; i >= 0; i--)
00569 {
00570 octave_idx_type xstart = idxa(i)(0), xstep = idxa(i)(1) - xstart;
00571 start = start * dvx(i) + xstart;
00572 step = step * dvx(i) + xstep;
00573 }
00574 retval = idx_vector::make_range (start, step, clen);
00575 }
00576 else
00577 {
00578 Array<octave_idx_type> idx (idxa(0).orig_dimensions ());
00579 octave_idx_type *idx_vec = idx.fortran_vec ();
00580
00581 for (octave_idx_type i = len - 1; i >= 0; i--)
00582 {
00583 if (i < len - 1)
00584 idxa(i).loop (clen, sub2ind_helper (idx_vec, dvx(i)));
00585 else
00586 idxa(i).copy_data (idx_vec);
00587 }
00588
00589 retval = idx_vector (idx);
00590 }
00591 }
00592 else
00593 current_liboctave_error_handler ("sub2ind: needs at least 2 indices");
00594
00595 return retval;
00596 }
00597
00598 Array<idx_vector>
00599 ind2sub (const dim_vector& dv, const idx_vector& idx)
00600 {
00601 octave_idx_type len = idx.length (0), n = dv.length ();
00602 Array<idx_vector> retval (dim_vector (n, 1));
00603 octave_idx_type numel = dv.numel ();
00604
00605 if (idx.extent (numel) > numel)
00606 current_liboctave_error_handler ("ind2sub: index out of range");
00607 else
00608 {
00609 if (idx.is_scalar ())
00610 {
00611 octave_idx_type k = idx(0);
00612 for (octave_idx_type j = 0; j < n; j++)
00613 {
00614 retval(j) = k % dv(j);
00615 k /= dv(j);
00616 }
00617 }
00618 else
00619 {
00620 OCTAVE_LOCAL_BUFFER (Array<octave_idx_type>, rdata, n);
00621
00622 dim_vector odv = idx.orig_dimensions ();
00623 for (octave_idx_type j = 0; j < n; j++)
00624 rdata[j] = Array<octave_idx_type> (odv);
00625
00626 for (octave_idx_type i = 0; i < len; i++)
00627 {
00628 octave_idx_type k = idx(i);
00629 for (octave_idx_type j = 0; j < n; j++)
00630 {
00631 rdata[j](i) = k % dv(j);
00632 k /= dv(j);
00633 }
00634 }
00635
00636 for (octave_idx_type j = 0; j < n; j++)
00637 retval(j) = rdata[j];
00638 }
00639
00640
00641 }
00642
00643 return retval;
00644 }
00645
00646 int
00647 permute_vector_compare (const void *a, const void *b)
00648 {
00649 const permute_vector *pva = static_cast<const permute_vector *> (a);
00650 const permute_vector *pvb = static_cast<const permute_vector *> (b);
00651
00652 return pva->pidx > pvb->pidx;
00653 }