Array-util.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2003-2012 John W. Eaton
00004 Copyright (C) 2009 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
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   // FIXME -- the solution using increment_index is not
00407   // efficient.
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   // Mark scalars and colons, count non-scalar indices.
00431   int nonsc = 0;
00432   bool all_colons = true;
00433   for (int i = 0; i < ial; i++)
00434     {
00435       // FIXME -- should we check for length() instead?
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   // If the number of nonscalar indices matches the dimensionality of
00444   // RHS, we try an exact match, inquiring even singleton dimensions.
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 // A helper class.
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           // All scalars case - the result is a scalar.
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           // All ranges case - the result is a range.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines