home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / src / idx-vector.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  6KB  |  342 lines

  1. // idx-vector.cc                                       -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include <iostream.h>
  29. #include <stdlib.h>
  30.  
  31. #include "dMatrix.h"
  32. #include "Range.h"
  33. #include "idx-vector.h"
  34. #include "user-prefs.h"
  35. #include "error.h"
  36. #include "utils.h"
  37.  
  38. idx_vector::idx_vector (const idx_vector& a)
  39. {
  40.   data = 0;
  41.   initialized = a.initialized;
  42.  
  43.   len = a.len;
  44.   if (len > 0)
  45.     {
  46.       data = new int [len];
  47.       for (int i = 0; i < len; i++)
  48.     data[i] = a.data[i];
  49.  
  50.       num_zeros = a.num_zeros;
  51.       num_ones = a.num_ones;
  52.       one_zero = a.one_zero;
  53.  
  54.       max_val = a.max_val;
  55.       min_val = a.min_val;
  56.     }
  57. }
  58.  
  59. static inline int
  60. tree_to_mat_idx (double x)
  61. {
  62.   if (x > 0)
  63.     return ((int) (x + 0.5) - 1);
  64.   else
  65.     return ((int) (x - 0.5) - 1);
  66. }
  67.  
  68. idx_vector::idx_vector (const Matrix& m, int do_ftn_idx,
  69.             const char *rc, int z_len)
  70. {
  71.   data = 0;
  72.   initialized = 0;
  73.  
  74.   int nr = m.rows ();
  75.   int nc = m.columns ();
  76.  
  77.   if (nr == 0 || nc == 0)
  78.     {
  79.       len = 0;
  80.       num_zeros = 0;
  81.       num_ones = 0;
  82.       one_zero = 0;
  83.       initialized = 1;
  84.       return;
  85.     }
  86.   else if (nr > 1 && nc > 1 && do_ftn_idx)
  87.     {
  88.       const double *cop_out = m.data ();
  89.       len = nr * nc;
  90.       data = new int [len];
  91.       for (int i = 0; i < len; i++)
  92.     data[i] = tree_to_mat_idx (*cop_out++);
  93.     }
  94.   else if (nr == 1 && nc > 0)
  95.     {
  96.       len = nc;
  97.       data = new int [len];
  98.       for (int i = 0; i < len; i++)
  99.     data[i] = tree_to_mat_idx (m.elem (0, i)); 
  100.     }  
  101.   else if (nc == 1 && nr > 0)
  102.     {
  103.       len = nr;
  104.       data = new int [len];
  105.       for (int i = 0; i < len; i++)
  106.     data[i] = tree_to_mat_idx (m.elem (i, 0));
  107.     }
  108.   else
  109.     {
  110.       ::error ("invalid matrix used as index");
  111.       return;
  112.     }
  113.  
  114.   init_state (rc, z_len);
  115. }
  116.  
  117. idx_vector::idx_vector (const Range& r)
  118. {
  119.   data = 0;
  120.   initialized = 0;
  121.  
  122.   len = r.nelem ();
  123.  
  124.   if (len < 0)
  125.     {
  126.       ::error ("invalid range used as index");
  127.       return;
  128.     }
  129.   else if (len == 0)
  130.     {
  131.       num_zeros = 0;
  132.       num_ones = 0;
  133.       one_zero = 0;
  134.       initialized = 1;
  135.       return;
  136.     }
  137.  
  138.   double b = r.base ();
  139.   double step = r.inc ();
  140.  
  141.   data = new int [len];
  142.  
  143.   for (int i = 0; i < len; i++)
  144.     {
  145.       double val = b + i * step;
  146.       data[i] = tree_to_mat_idx (val);
  147.     }
  148.  
  149.   init_state ();
  150. }
  151.  
  152. idx_vector&
  153. idx_vector::operator = (const idx_vector& a)
  154. {
  155.   if (this != &a)
  156.     {
  157.       initialized = a.initialized;
  158.  
  159.       delete [] data;
  160.       len = a.len;
  161.       data = new int [len];
  162.       for (int i = 0; i < len; i++)
  163.     data[i] = a.data[i];
  164.  
  165.       num_zeros = a.num_zeros;
  166.       num_ones = a.num_ones;
  167.       one_zero = a.one_zero;
  168.  
  169.       max_val = a.max_val;
  170.       min_val = a.min_val;
  171.     }
  172.   return *this;
  173. }
  174.  
  175. void
  176. idx_vector::init_state (const char *rc, int z_len)
  177. {
  178.   one_zero = 1;
  179.   num_zeros = 0;
  180.   num_ones = 0;
  181.  
  182.   min_val = max_val = data[0];
  183.  
  184.   int i = 0;
  185.   do
  186.     {
  187.       if (data[i] == -1)
  188.     num_zeros++;
  189.       else if (data[i] == 0)
  190.     num_ones++;
  191.  
  192.       if (one_zero && data[i] != -1 && data[i] != 0)
  193.     one_zero = 0;
  194.  
  195.       if (data[i] > max_val)
  196.     max_val = data[i];
  197.  
  198.       if (data[i] < min_val)
  199.     min_val = data[i];
  200.     }
  201.   while (++i < len);
  202.  
  203.   if (one_zero && z_len == len)
  204.     {
  205.       if (num_ones != len || user_pref.prefer_zero_one_indexing)
  206.     convert_one_zero_to_idx ();
  207.     }
  208.   else if (min_val < 0)
  209.     {
  210.       ::error ("%s index %d out of range", rc, min_val+1);
  211.       initialized = 0;
  212.       return;
  213.     }
  214. #if 0
  215. // Checking max index against size won't work right here unless we
  216. // also look at resize on range error, and we have to do that later
  217. // on anyway.
  218.  
  219.   else if (max_val >= z_len)
  220.     {
  221.       ::error ("%s index %d out of range", rc, max_val+1);
  222.       initialized = 0;
  223.       return;
  224.     }
  225. #endif
  226.  
  227.   initialized = 1;
  228. }
  229.  
  230. void
  231. idx_vector::convert_one_zero_to_idx (void)
  232. {
  233.   if (num_ones == 0)
  234.     {
  235.       len = 0;
  236.       max_val = 0;
  237.       min_val = 0;
  238.       delete [] data;
  239.       data = 0;
  240.     }
  241.   else
  242.     {
  243.       assert (num_ones + num_zeros == len);
  244.  
  245.       int *new_data = new int [num_ones];
  246.       int count = 0;
  247.       for (int i = 0; i < len; i++)
  248.     if (data[i] == 0)
  249.       new_data[count++] = i;
  250.  
  251.       delete [] data;
  252.       len = num_ones;
  253.       data = new_data;
  254.  
  255.       min_val = max_val = data[0];
  256.  
  257.       i = 0;
  258.       do
  259.     {
  260.       if (data[i] > max_val)
  261.         max_val = data[i];
  262.  
  263.       if (data[i] < min_val)
  264.         min_val = data[i];
  265.     }
  266.       while (++i < len);
  267.     }
  268. }
  269.  
  270. static inline int
  271. intcmp (int *i, int *j)
  272. {
  273.   return (*i - *j);
  274. }
  275.  
  276. int
  277. idx_vector::checkelem (int n) const
  278. {
  279.   if (n < 0 || n >= len)
  280.     {
  281.       ::error ("idx-vector: index out of range");
  282.       return 0;
  283.     }
  284.  
  285.   return elem (n);
  286. }
  287.  
  288. void
  289. idx_vector::sort (void)
  290. {
  291.   qsort ((void *) data, len, sizeof (int),
  292.      (int (*)(const void*, const void*)) intcmp); 
  293. }
  294.  
  295. void
  296. idx_vector::sort_uniq (void)
  297. {
  298.   if (len > 0)
  299.     {
  300.       sort ();
  301.  
  302.       int *new_data = new int [len];
  303.       new_data[0] = data[0];
  304.       int k = 0;
  305.       for (int i = 1; i < len; i++)
  306.     {
  307.       if (data[i] != new_data[k])
  308.         {
  309.           k++;
  310.           new_data[k] = data[i];
  311.         }
  312.     }
  313.       delete [] data;
  314.       len = k+1;
  315.       data = new_data;
  316.     }
  317. }
  318.  
  319. void
  320. idx_vector::shorten (int n)
  321. {
  322.   if (n > 0 && n <= len)
  323.     len = n;
  324.   else
  325.     panic_impossible ();
  326. }
  327.  
  328. ostream&
  329. operator << (ostream& os, const idx_vector& a)
  330. {
  331.   for (int i = 0; i < a.len; i++)
  332.     os << a.data[i] << "\n";
  333.   return os;
  334. }
  335.  
  336. /*
  337. ;;; Local Variables: ***
  338. ;;; mode: C++ ***
  339. ;;; page-delimiter: "^/\\*" ***
  340. ;;; End: ***
  341. */
  342.