################################################################## ### # # File: Ap.rb # # Subject: Main Methods for arbitrary precision. # # Author: Dennis J. Darland # # Date: April 2, 2007 # ############################################################################ # # Copyright (C) 2007 Dennis J. Darland# # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################ if NUM_DIGITS <= 12 then require "rapfp/Real" Apfp_Mode = 0 $Ap = Real $ApConst = RealConst else require "rapfp/Apfp" Apfp_Mode = 1 $Ap = Apfp $ApConst = ApfpConst end def ap_in(str) str = str.to_s str = elim_b(str) found = 0 f_mant_re1 = Regexp.new("^-?[0-9]+\.[0-9]+") f_mant_re2 = Regexp.new("^-?[0-9]+") if str =~ f_mant_re1 mant = "#{$&}" rest = "#{$'}" found = 1 elsif str =~ f_mant_re2 mant = "#{$&}" + ".0" rest = "#{$'}" found = 1 end if found == 1 then restsav = rest.clone if rest != "" && rest[0].chr != "+" then f_sep_re = Regexp.new("^e|E") if rest =~ f_sep_re rest = "#{$'}" restsav = rest.clone f_expt_re = Regexp.new("^[-+]?[0-9]+") if rest =~ f_expt_re expt = "#{$&}" rest = "#{$'}" else if RAILS_MODE == 0 then puts "ERROR 1 ap_in #{str}" 1/0 end return "BAD" end else expt = "0" rest = restsav end else expt = "0" rest = restsav end if rest != "" f_sep_err_re = Regexp.new("^\\+/-") if rest =~ f_sep_err_re rest = "#{$'}" f_mant_err_re = Regexp.new("^-?[0-9]+\.[0-9]+") if rest =~ f_mant_err_re mant_err = "#{$&}" rest = "#{$'}" if rest != "" f_sep_re = Regexp.new("^e|E") if rest =~ f_sep_re rest = "#{$'}" f_expt_err_re = Regexp.new("^[-+]?[0-9]+") if rest =~ f_expt_err_re expt_err = "#{$&}" else if RAILS_MODE == 0 then puts "ERROR 2 ap_in #{str}" 1/0 end return "BAD" end else expt_err = "0" end else expt_err = "0" end else if RAILS_MODE == 0 then puts "ERROR 3 ap_in #{str}" 1/0 end return "BAD" end else if RAILS_MODE == 0 then puts "ERROR 4 ap_in #{str}" 1/0 end return "BAD" end else mant_err = "0" expt_err = "0" end if Apfp_Mode == 0 # built in floats if mant_err == "0" return $Ap.new("#{mant}e#{expt}".to_f,"#{mant}e#{expt}".to_f*Float::EPSILON) else return $Ap.new("#{mant}e#{expt}".to_f,"#{mant_err}e#{expt_err}".to_f) end else #Apfp floats mant = mant.to_s rmant = mant.reverse if rmant =~ /^[0-9]*\./ cnt = "#{$&}".size mant.sub!(/\./,"") expt = expt.to_i - cnt + 1 elsif rmant =~ /^[0-9]*/ #do nothing else if RAILS_MODE == 0 then puts "ap_in match B failed" puts "mant = " + mant.to_s 1/0 end return "BAD" end if mant_err != "0" rmant = mant_err.reverse if rmant =~ /^[0-9]*\./ cnt = "#{$&}".size mant_err.sub!(/\./,"") expt_err = expt_err.to_i - cnt + 1 else if RAILS_MODE == 0 then puts "ap_in match C failed" 1/0 end return "BAD" end end # puts "Ap.rb mant = #{mant} expt = #{expt.to_s} err = #{mant_err} expt_err = #{expt_err}" if mant_err == "0" return Apfp.new(mant.to_i,expt.to_i,50,-NUM_DIGITS+expt.to_i+mant.to_s.size).norm else return Apfp.new(mant.to_i,expt.to_i,mant_err.to_i,expt_err.to_i).norm end end else if RAILS_MODE == 0 then puts "ERROR 5 ap_in #{str}" 1/0 end return "BAD" end end def elim_b(str) out = "" len = str.size pos = 0 while pos < len do if str[pos].chr != " " then # puts "out = " + out.to_s # puts "str = " + str.to_s # puts "pos = " + pos.to_s out = out + str[pos].chr end pos += 1 end return out end def ap_int(v) if Apfp_Mode == 0 c0(Real.new(v.to_f,v*Float::EPSILON)) else if v >= 0 then Apfp.new(v.to_i,0,50,(((v.to_i).to_s).size)-NUM_DIGITS).norm else Apfp.new(v.to_i,0,50,((((-v).to_i).to_s).size)-NUM_DIGITS).norm end end end # now returns error same as c (not sure if is should - used in Sode.rb for # increment etc which in a way cannot have error. def c0(val) unless val.kind_of?(Fixnum) || val.kind_of?(Integer) v = val.to_s return(ap_in(v)) else return ap_int(val) end end def c(val) unless val.kind_of?(Fixnum) || val.kind_of?(Integer) v = val.to_s return(ap_in(v)) else return ap_int(val) end end def ap_min(a,b) if a < b then return a else return b end end def ap_max(a,b) if a > b then return a else return b end end require "rapfp/Apc"