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 / liboctave / Range.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  5KB  |  217 lines

  1. // Range.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 <limits.h>
  30.  
  31. #include "Range.h"
  32. #include "dMatrix.h"
  33.  
  34. Matrix
  35. Range::matrix_value (void) const
  36. {
  37.   Matrix retval;
  38.  
  39.   if (rng_nelem > 0)
  40.     {
  41.       retval.resize (1, rng_nelem);
  42.       double b = rng_base;
  43.       double increment = rng_inc;
  44.       for (int i = 0; i < rng_nelem; i++)
  45.     retval.elem (0, i) = b + i * increment;
  46.     }
  47.  
  48.   return retval;
  49. }
  50.  
  51. // NOTE: max and min only return useful values if nelem > 0.
  52.  
  53. double
  54. Range::min (void) const
  55. {
  56.   double retval = 0.0;
  57.   if (rng_nelem > 0)
  58.     {
  59.       if (rng_inc > 0)
  60.     retval = rng_base;
  61.       else
  62.     retval = rng_base + (rng_nelem - 1) * rng_inc;
  63.     }
  64.   return retval;
  65. }
  66.  
  67. double
  68. Range::max (void) const
  69. {
  70.   double retval = 0.0;
  71.   if (rng_nelem > 0)
  72.     {
  73.       if (rng_inc > 0)
  74.     retval = rng_base + (rng_nelem - 1) * rng_inc;
  75.       else
  76.     retval = rng_base;
  77.     }
  78.   return retval;
  79. }
  80.  
  81. void
  82. Range::sort (void)
  83. {
  84.   if (rng_base > rng_limit && rng_inc < 0.0)
  85.     {
  86.       double tmp = rng_base;
  87.       rng_base = min ();
  88.       rng_limit = tmp;
  89.       rng_inc = -rng_inc;
  90.     }
  91. }
  92.  
  93. void
  94. Range::print_range (void)
  95. {
  96.   cerr << "Range: rng_base = " << rng_base
  97.        << " rng_limit " << rng_limit
  98.        << " rng_inc " << rng_inc
  99.        << " rng_nelem " << rng_nelem << "\n";
  100. }
  101.  
  102. ostream&
  103. operator << (ostream& os, const Range& a)
  104. {
  105.   double b = a.base ();
  106.   double increment = a.inc ();
  107.   int num_elem = a.nelem ();
  108.  
  109.   for (int i = 0; i < num_elem; i++)
  110.     os << b + i * increment << " ";
  111.  
  112.   os << "\n";
  113.  
  114.   return os;
  115. }
  116.  
  117. istream&
  118. operator >> (istream& is, Range& a)
  119. {
  120.   is >> a.rng_base;
  121.   if (is)
  122.     {
  123.       is >> a.rng_limit;
  124.       if (is)
  125.     {
  126.       is >> a.rng_inc;
  127.       a.rng_nelem = a.nelem_internal ();
  128.     }
  129.     }
  130.  
  131.   return is;
  132. }
  133.  
  134. int
  135. Range::nelem_internal (void) const
  136. {
  137. // Find an approximate number of intervals, then do the best we can to
  138. // find the number of intervals that we would get if we had done
  139. // something like
  140. //
  141. //   nelem = 0;
  142. //   while (base + nelem * inc <= limit)
  143. //     nelem++;
  144. //
  145. // (for limit > base && inc > 0)
  146. //
  147. // The number of elements in the range is one greater than the number
  148. // of intervals.
  149.  
  150. // We can't have more than INT_MAX elements in the range.
  151.  
  152.   double d_n_intervals = (rng_limit - rng_base) / rng_inc;
  153.   int max_intervals = INT_MAX - 1;
  154.   double d_max_val = (double) max_intervals;
  155.  
  156.   if (d_n_intervals > d_max_val)
  157.     return -1;
  158.  
  159.   int n_intervals = (d_n_intervals > 0)
  160.     ? ((int) (d_n_intervals + 0.5))
  161.     : ((int) (d_n_intervals - 0.5)); 
  162.  
  163.   if (rng_limit > rng_base && rng_inc > 0)
  164.     {
  165. // Our approximation may have been too big.
  166.  
  167.       while (rng_base + n_intervals * rng_inc > rng_limit && n_intervals > 0)
  168.     n_intervals--;
  169.  
  170. // Now that we are close, get the actual number.  Try to avoid
  171. // problems with extended precision registers.
  172.  
  173.       for (;;)
  174.     {
  175.       volatile double tmp_inc = (n_intervals + 1) * rng_inc;
  176.       volatile double tmp_val = rng_base + tmp_inc;
  177.       if (tmp_val <= rng_limit && n_intervals < max_intervals)
  178.         n_intervals++;
  179.       else
  180.         break;
  181.     }
  182.     }
  183.   else if (rng_limit < rng_base && rng_inc < 0)
  184.     {
  185. // Our approximation may have been too big.
  186.  
  187.       while (rng_base + n_intervals * rng_inc < rng_limit && n_intervals > 0)
  188.     n_intervals--;
  189.  
  190. // Now that we are close, get the actual number.  Try to avoid
  191. // problems with extended precision registers.
  192.  
  193.       for (;;)
  194.     {
  195.       volatile double tmp_inc = (n_intervals + 1) * rng_inc;
  196.       volatile double tmp_val = rng_base + tmp_inc;
  197.       if (tmp_val >= rng_limit && n_intervals < max_intervals)
  198.         n_intervals++;
  199.       else
  200.         break;
  201.     }
  202.     }
  203.   else if (rng_limit == rng_base)
  204.     n_intervals = 0;
  205.   else
  206.     n_intervals = -1;
  207.  
  208.   return (n_intervals >= max_intervals) ? -1 : n_intervals + 1;
  209. }
  210.  
  211. /*
  212. ;;; Local Variables: ***
  213. ;;; mode: C++ ***
  214. ;;; page-delimiter: "^/\\*" ***
  215. ;;; End: ***
  216. */
  217.