[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/5.10.0/ -> bigrat.pl (source)

   1  package bigrat;
   2  require  "bigint.pl";
   3  #
   4  # This library is no longer being maintained, and is included for backward
   5  # compatibility with Perl 4 programs which may require it.
   6  #
   7  # In particular, this should not be used as an example of modern Perl
   8  # programming techniques.
   9  #
  10  # Arbitrary size rational math package
  11  #
  12  # by Mark Biggar
  13  #
  14  # Input values to these routines consist of strings of the form 
  15  #   m|^\s*[+-]?[\d\s]+(/[\d\s]+)?$|.
  16  # Examples:
  17  #   "+0/1"                          canonical zero value
  18  #   "3"                             canonical value "+3/1"
  19  #   "   -123/123 123"               canonical value "-1/1001"
  20  #   "123 456/7890"                  canonical value "+20576/1315"
  21  # Output values always include a sign and no leading zeros or
  22  #   white space.
  23  # This package makes use of the bigint package.
  24  # The string 'NaN' is used to represent the result when input arguments 
  25  #   that are not numbers, as well as the result of dividing by zero and
  26  #       the sqrt of a negative number.
  27  # Extreamly naive algorthims are used.
  28  #
  29  # Routines provided are:
  30  #
  31  #   rneg(RAT) return RAT                negation
  32  #   rabs(RAT) return RAT                absolute value
  33  #   rcmp(RAT,RAT) return CODE           compare numbers (undef,<0,=0,>0)
  34  #   radd(RAT,RAT) return RAT            addition
  35  #   rsub(RAT,RAT) return RAT            subtraction
  36  #   rmul(RAT,RAT) return RAT            multiplication
  37  #   rdiv(RAT,RAT) return RAT            division
  38  #   rmod(RAT) return (RAT,RAT)          integer and fractional parts
  39  #   rnorm(RAT) return RAT               normalization
  40  #   rsqrt(RAT, cycles) return RAT       square root
  41  
  42  # Convert a number to the canonical string form m|^[+-]\d+/\d+|.
  43  sub main'rnorm { #(string) return rat_num
  44      local($_) = @_;
  45      s/\s+//g;
  46      if (m#^([+-]?\d+)(/(\d*[1-9]0*))?$#) {
  47      &norm($1, $3 ? $3 : '+1');
  48      } else {
  49      'NaN';
  50      }
  51  }
  52  
  53  # Normalize by reducing to lowest terms
  54  sub norm { #(bint, bint) return rat_num
  55      local($num,$dom) = @_;
  56      if ($num eq 'NaN') {
  57      'NaN';
  58      } elsif ($dom eq 'NaN') {
  59      'NaN';
  60      } elsif ($dom =~ /^[+-]?0+$/) {
  61      'NaN';
  62      } else {
  63      local($gcd) = &'bgcd($num,$dom);
  64      $gcd =~ s/^-/+/;
  65      if ($gcd ne '+1') { 
  66          $num = &'bdiv($num,$gcd);
  67          $dom = &'bdiv($dom,$gcd);
  68      } else {
  69          $num = &'bnorm($num);
  70          $dom = &'bnorm($dom);
  71      }
  72      substr($dom,$[,1) = '';
  73      "$num/$dom";
  74      }
  75  }
  76  
  77  # negation
  78  sub main'rneg { #(rat_num) return rat_num
  79      local($_) = &'rnorm(@_);
  80      tr/-+/+-/ if ($_ ne '+0/1');
  81      $_;
  82  }
  83  
  84  # absolute value
  85  sub main'rabs { #(rat_num) return $rat_num
  86      local($_) = &'rnorm(@_);
  87      substr($_,$[,1) = '+' unless $_ eq 'NaN';
  88      $_;
  89  }
  90  
  91  # multipication
  92  sub main'rmul { #(rat_num, rat_num) return rat_num
  93      local($xn,$xd) = split('/',&'rnorm($_[$[]));
  94      local($yn,$yd) = split('/',&'rnorm($_[$[+1]));
  95      &norm(&'bmul($xn,$yn),&'bmul($xd,$yd));
  96  }
  97  
  98  # division
  99  sub main'rdiv { #(rat_num, rat_num) return rat_num
 100      local($xn,$xd) = split('/',&'rnorm($_[$[]));
 101      local($yn,$yd) = split('/',&'rnorm($_[$[+1]));
 102      &norm(&'bmul($xn,$yd),&'bmul($xd,$yn));
 103  }
 104  
 105  # addition
 106  sub main'radd { #(rat_num, rat_num) return rat_num
 107      local($xn,$xd) = split('/',&'rnorm($_[$[]));
 108      local($yn,$yd) = split('/',&'rnorm($_[$[+1]));
 109      &norm(&'badd(&'bmul($xn,$yd),&'bmul($yn,$xd)),&'bmul($xd,$yd));
 110  }
 111  
 112  # subtraction
 113  sub main'rsub { #(rat_num, rat_num) return rat_num
 114      local($xn,$xd) = split('/',&'rnorm($_[$[]));
 115      local($yn,$yd) = split('/',&'rnorm($_[$[+1]));
 116      &norm(&'bsub(&'bmul($xn,$yd),&'bmul($yn,$xd)),&'bmul($xd,$yd));
 117  }
 118  
 119  # comparison
 120  sub main'rcmp { #(rat_num, rat_num) return cond_code
 121      local($xn,$xd) = split('/',&'rnorm($_[$[]));
 122      local($yn,$yd) = split('/',&'rnorm($_[$[+1]));
 123      &bigint'cmp(&'bmul($xn,$yd),&'bmul($yn,$xd));
 124  }
 125  
 126  # int and frac parts
 127  sub main'rmod { #(rat_num) return (rat_num,rat_num)
 128      local($xn,$xd) = split('/',&'rnorm(@_));
 129      local($i,$f) = &'bdiv($xn,$xd);
 130      if (wantarray) {
 131      ("$i/1", "$f/$xd");
 132      } else {
 133      "$i/1";
 134      }   
 135  }
 136  
 137  # square root by Newtons method.
 138  #   cycles specifies the number of iterations default: 5
 139  sub main'rsqrt { #(fnum_str[, cycles]) return fnum_str
 140      local($x, $scale) = (&'rnorm($_[$[]), $_[$[+1]);
 141      if ($x eq 'NaN') {
 142      'NaN';
 143      } elsif ($x =~ /^-/) {
 144      'NaN';
 145      } else {
 146      local($gscale, $guess) = (0, '+1/1');
 147      $scale = 5 if (!$scale);
 148      while ($gscale++ < $scale) {
 149          $guess = &'rmul(&'radd($guess,&'rdiv($x,$guess)),"+1/2");
 150      }
 151      "$guess";          # quotes necessary due to perl bug
 152      }
 153  }
 154  
 155  1;


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1