Merge branch 'master' of ssh://git.code.sf.net/p/maxima/code
[maxima.git] / share / numeric / decfp-core.lisp
blob98cb62d35c39ec19a33dc8ef538e053be197d294
1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
3 (in-package :maxima)
4 (declare-top (special *m fpprec $fpprec $float $bfloat $ratprint $ratepsilon $domain $m1pbranch
5 $rounddecimalfloats machine-mantiss-precision))
7 (defvar $rounddecimalfloats nil)
9 ;;; test case
10 #|
11 sum:0$
12 for i: 1 thru 50 do sum:sum+decbfloat(9/10^i) ;
13 is (sum<1) ; should be true
14 is (sum+1/10^50=1.0L0) ; should be true
17 ;;; REVISED 1/2016 to use decimal fpprec, input, output and inside.
18 ;;;;Revised 2/2016 to allow BOTH decimal and binary
19 ;;; RJF.
20 ;;; Revised 3/19/2016 to allow printing of decimal bigfloats with wxmaxima
21 ;;; Revised 3/19/2016 to include $rationalize.
22 ;; rl():=load("c:/lisp/decfp.lisp")
23 ;;;; problems to be expected:
25 ;;; 1. There is a possibility that there are programs
26 ;;; that expect binary radix.
28 ;;; 2. I started to write the output code so that the decimal point is on
29 ;;; the right of the mantissa. That is 1/2 is 5 X 10^(-1).
30 ;;; I suppose I could do this, for decimal precision 4, do 5000 x 10^-(-4).
32 ;;; This latter version has the property that precision can be
33 ;;; deduced from the length of the fraction part, except for 0x10^0.
34 ;;; The previous binary version put the binary point on the left.
35 ;;; so in binary precision 10, the code would be 1024 x 2^(-11)
36 ;;; we store the precision in the header, nevertheless, for speed.
37 ;;;;;;;;;;;;;;
40 ;; some decimal functions
42 ;; Reduce the number of decimal digits in a decimal bigfloat B
43 ;; to the number specified
45 (defun $decimalfptrim(B) ; B is a bigfloat
46 (if (decimalfpp B)
47 (cons (car B)(decimalfptrim (cdr B) t)) ;;trim excess digits
48 ($bfloat B))) ;; if its binary, $bfloat should trim it
50 ;; decimalfptrim will carefully round
52 (defun decimalfptrim(f &optional (flag $rounddecimalfloats)) ;; f is (significand exponent)
53 (let ((s (car f))
54 (e (cadr f)))
55 (cond((eql s 0)(list 0 0))
57 ;; first remove trailing zeros
58 (while (= (mod s 10) 0)(setf s (truncate s 10))(incf e))
59 ;; there may still be more digits than allowed by $fpprec
60 (if flag
61 (let ((adjust (- (flatsize10 s) $fpprec)))
62 ;;; (format t"~%in decimalfptrim, s=~s, adjust=~s~%" s adjust)
63 (if (<= adjust 0) (list s e)
64 (decimalround s e adjust) ))
65 (list s e) ;; don't round!
67 )))))
69 (defun decimalround (s e ad) ; we want to remove ad digits from the right
70 (let*((guard 0) ; this is the guard digit
71 (sign (signum s)))
72 ;significand with one extra (guard) digit
73 ;sticky has the rest
74 (multiple-value-bind
75 (swithguard sticky)
76 (truncate s (expt 10 (1- ad)))
77 ;; now have last digit of s, the one to drop off, at left end of swithguard
78 (setf guard (mod swithguard 10))
79 ;;; (format t "~% in decimalround swg=~s guard=~s sign=~s~%" swithguard guard sign)
80 ;; because (mod 13 10) is 3, (mod -13 10) is 7...
81 ;; round 13b0 to 1b0, round -13 to -1b0 in 1 digit..
83 ;; because (mod 18 10) is 8, (mod -18 10) is 2
84 ;; round 18 to 2 round -18 to -2
86 ;; now consider round-to-even
87 ;; because (mod 15 10) is 5 and 1 is odd, round to 2.
88 ;; because (mod -15 10) is 5 and 1 is odd, round to -2.
90 (decimalfptrim
91 (list (cond ((= sign 1)
92 (cond ((< guard 5) (truncate swithguard 10)) ; no sweat
93 ;; in case we have 96 b0 we round up and get 10b0. too many digits
94 ;; so in the case of xxxx99X, or worse 9999.999X we need to re-trim.
95 ((or (> guard 5)
96 (and (= guard 5)(> sticky 0)))
97 (1+ (truncate swithguard 10))) ;no sweat again.
99 ;; guard digit is 5 and sticky is 0. (cannot be negative if sign is 1)
100 ;; so find the even digit at or above this number
101 (let* ((snoguard(truncate swithguard 10))
102 (checkthis (mod snoguard 10)))
103 (if (evenp checkthis)(list snoguard (+ e ad)) ; this is already even
104 (1+ snoguard))))))
106 ;;; i.e. sign=-1, because sign=0 can't happen
107 (cond ((> guard 5) (truncate swithguard 10))
108 ((or (< guard 5)
109 (and (= guard 5)(< sticky 0)))
110 (1- (truncate swithguard 10)))
111 ;; guard digit is 5 and sticky is 0 (cannot be pos if sign is -1)
112 (t (let* ((snoguard(truncate swithguard 10))
113 (checkthis (mod snoguard 10)))
114 (if (evenp checkthis)snoguard ; this is already even
115 (1- snoguard)))))))
116 (+ e ad))))))
118 (defun flatsize10(r) (if (= r 0) 1
119 (ceiling (* #.(log 2)(integer-length (abs r))) #.(log 10 ))))
121 (defvar *m)
123 ;; *DECFP = T if the computation is being done in decimal radix. NIL implies
124 ;; base 2.
125 ;;;originally, Decimal radix was used only during output.
126 ;;; now -- in this file it is used all the time... 1/2016/RJf
128 ;; Representation of a decimal Bigfloat: ((BIGFLOAT SIMP precision DECIMAL) significand exponent)
129 ;; significand and exponent and precision are all integers.
130 ;; NOW -- number of decimal digits 1/2016
131 ;; precision >= (integer-length (abs significand))) =( flatsize10 significand)
132 ;; NOW The actual number represented is (* significand (^ 10 exponent)).
134 ;; for decimals, we use $fpprec which is the decimal digit count.
135 ;; the derived number fpprec (no $) is the approximate number
136 ;; of binary bits, computed by fpprec1 when $fpprec is set, used by the binary arithmetic.
139 (defun dim-bigfloat (form result)
140 (let (($lispdisp nil))
141 (dimension-atom (maknam (decfpformat form)) result)))
143 ;; needed for wxmaxima front end.
144 (defun wxxml-bigfloat (x l r) (append l '("<n>") (decfpformat x) '("</n>") r))
147 (defun decimalfpp(x)(and (consp x)
148 (eq (caar x) 'bigfloat)
149 (member 'decimal (cddar x)))) ; decimal bigfloat predicate
150 (defun binaryfpp(x)(and (consp x)
151 (eq (caar x) 'bigfloat)
152 (not(member 'decimal (cddar x))))) ; binary bigfloat predicate
155 ;; Converts the bigfloat L to list of digits including |.| and the
156 ;; exponent marker |b|. The number of significant digits is controlled
157 ;; by $fpprintprec.
159 ;; uses L marker instead of b. 123b0 prints 1.23L2
161 (defun decfpformat (l)
162 (if (decimalfpp l)
163 (cond ((= (cadr l) 0) '(|0| |.| |L| |0|))
164 ((> (cadr l) 0)
165 (let ((M(explodec (format nil "~s"(cadr l)))))
166 (append (cons (car M)(cons '|.| (cdr M))) '(|L|)(explodec(+ (caddr l)(length M) -1)))))
168 (t (let ((M(explodec (format nil "~s"(cadr l)))))
169 (append (cons '|-|(cons (car M)(cons '|.| (cdr M))))'(|L|)(explodec(+ (caddr l)(length M) -1))))))
170 ;; oh, it's a binary bigfloat
171 (fpformat l)))
174 ;; Tells you if you have a bigfloat object. BUT, if it is a binary bigfloat,
175 ;; it will normalize it by making the precision of the bigfloat match
176 ;; the current precision setting in $fpprec. And it will also convert
177 ;; bogus zeroes (mantissa is zero, but exponent is not) to a true
178 ;; zero.
179 ;; overwrites the standard bigfloatp
181 (defun bigfloatp (x)
182 (cond ((decimalfpp x) x)
183 ;; A bigfloat object looks like '((bigfloat simp <prec>) <mantissa> <exp>)
184 ;; just copy out the same stuff from float.lisp
186 - (prog nil
187 (cond ((not ($bfloatp x)) (return nil))
188 ((= fpprec (caddar x))
189 ;; Precision matches. (Should we fix up bogus bigfloat
190 ;; zeros?)
191 (return x))
192 ((> fpprec (caddar x))
193 ;; Current precision is higher than bigfloat precision.
194 ;; Scale up mantissa and adjust exponent to get the
195 ;; correct precision.
196 (setq x (bcons (list (fpshift (cadr x) (- fpprec (caddar x)))
197 (caddr x)))))
199 ;; Current precision is LOWER than bigfloat precision.
200 ;; Round the number to the desired precision.
201 (setq x (bcons (list (fpround (cadr x))
202 (+ (caddr x) *m fpprec (- (caddar x))))))))
203 ;; Fix up any bogus zeros that we might have created.
204 (return (if (equal (cadr x) 0) (bcons (list 0 0)) x)))
207 ;; overwrite this one, too
208 (defun bigfloat2rat (x)
209 (if (decimalfpp x) (let ((k (* (cadr x)(expt 10 (caddr x)))))
210 (list '(rat) (numerator k)(denominator k)))
211 (let ()
212 (setq x (bigfloatp x))
213 (let (($float2bf t)
214 (exp nil)
215 (y nil)
216 (sign nil))
217 (setq exp (cond ((minusp (cadr x))
218 (setq sign t
219 y (fpration1 (cons (car x) (fpabs (cdr x)))))
220 (rplaca y (* -1 (car y))))
221 (t (fpration1 x))))
222 (when $ratprint
223 (princ "`rat' replaced ")
224 (when sign (princ "-"))
225 (princ (maknam (fpformat (cons (car x) (fpabs (cdr x))))))
226 (princ " by ")
227 (princ (car exp))
228 (write-char #\/)
229 (princ (cdr exp))
230 (princ " = ")
231 (setq x ($bfloat (list '(rat simp) (car exp) (cdr exp))))
232 (when sign (princ "-"))
233 (princ (maknam (fpformat (cons (car x) (fpabs (cdr x))))))
234 (terpri))
235 exp))))
237 ;; Convert a machine floating point number into a bigfloat.
238 ;; Since it is a binary float, no point in making it decimal..
239 ;; Probably we don't do this a lot, so we just do it
240 ;; with a short program.
241 (defun decfloat-from-fp (x) ($binarybfloat ($rationalize x)))
243 ;; Convert a bigfloat into a floating point number.
244 (defun fp2flo(l)(decfp2flo l)) ; redefine usual
245 (defun decfp2flo (l)
246 (if (decimalfpp l)
247 (coerce (* (cadr l)(expt 10 (caddr l))) 'double-float)
248 (let ((precision (caddar l))
249 (mantissa (cadr l))
250 (exponent (caddr l))
251 (fpprec machine-mantissa-precision)
252 (*m 0))
253 ;; Round the mantissa to the number of bits of precision of the
254 ;; machine, and then convert it to a floating point fraction. We
255 ;; have 0.5 <= mantissa < 1
256 (setq mantissa (quotient (fpround mantissa) (expt 2.0 machine-mantissa-precision)))
257 ;; Multiply the mantissa by the exponent portion. I'm not sure
258 ;; why the exponent computation is so complicated.
260 ;; GCL doesn't signal overflow from scale-float if the number
261 ;; would overflow. We have to do it this way. 0.5 <= mantissa <
262 ;; 1. The largest double-float is .999999 * 2^1024. So if the
263 ;; exponent is 1025 or higher, we have an overflow.
264 (let ((e (+ exponent (- precision) *m machine-mantissa-precision)))
265 (if (>= e 1025)
266 (merror (intl:gettext "float: floating point overflow converting ~:M") l)
267 (scale-float mantissa e))))
270 (defun decbcons (s)
271 `((bigfloat simp ,$fpprec decimal) . ,(decimalfptrim s)))
273 ;; probably not useful. We only allow new decimal bigfloats
274 ;; if they are typed in as 1.2L0 etc Or maybe if they are integers??
277 (defun $bfloat (x) ;; used by too many other programs. need to replace it here
278 (cond
279 ((bigfloatp x)) ; return x, possibly changed precision
280 ((numberp x) ;; favors decimal conversion for CL numbers
281 (decintofp x))
282 #+ignore
283 ((numberp x) ;; favors binary conversion for CL numbers
284 (bcons (intofp x)))
285 ((atom x)($binarybfloat x)) ; %pi, %phi
286 ((eq (caar x) 'rat)
287 (decrat2fp x))
288 ((and(eq (caar x) 'mexpt)
289 (decimalfpp (cadr x))
290 (integerp (caddr x))
291 (>= (caddr x) 0))
292 (decfppower (cadr x)(caddr x))) ; float^integer
294 ((eq (caar x) 'mtimes)
295 (dectimesbigfloat (mapcar #'$decbfloat(cdr x)))) ;; not enough.?
297 ((eq (caar x) 'mplus)
298 (decaddbigfloat (mapcar #'$decbfloat(cdr x))))
300 ;; here we return to the previous program
301 (t ($binarybfloat x))))
303 (defun $decbfloat (x)
304 (cond
305 ((decimalfpp x)
306 (if (null $rounddecimalfloats) x ; just return it
307 (decbcons (decimalfptrim (cdr x))))); possibly chop/round it
310 ((numberp x) ;; favors decimal conversion for CL numbers
311 (decrat2fp x))
312 ((atom x)($binarybfloat x)) ; %pi, %phi
313 ((eq (caar x) 'rat)
314 (decrat2fp x))
315 ((and(eq (caar x) 'mexpt)
316 (decimalfpp (cadr x))
317 (integerp (caddr x))
318 (>= (caddr x) 0))
319 (decfppower (cadr x)(caddr x))) ; float^integer
320 ;; here we return to the previous program
322 (t ($binarybfloat x))))
324 (defun decfppower (ba e) ;ba^e, e is nonneg int
325 (let ((ans '(1 0))
326 (b (cdr ba)))
327 (dotimes (i e (decbcons (decimalfptrim ans))) (setf ans (decfptimes ans b)))))
329 (defun $binarybfloat (x &aux (y nil))
330 (cond ((setf y (bigfloatp x)) y )
331 ((or (numberp x)
332 (member x '($%e $%pi $%gamma) :test #'eq))
333 (bcons (intofp x)))
334 ((or (atom x) (member 'array (cdar x) :test #'eq))
335 (if (eq x '$%phi)
336 ($binarybfloat '((mtimes simp)
337 ((rat simp) 1 2)
338 ((mplus simp) 1 ((mexpt simp) 5 ((rat simp) 1 2)))))
340 ((eq (caar x) 'mexpt)
341 (if (equal (cadr x) '$%e)
342 (*fpexp (decfp2binfp (caddr x))) ;; exp(x)
343 (exptbigfloat (decfp2binfp (cadr x)) (decfp2binfp(caddr x)))))
344 ((eq (caar x) 'mncexpt)
345 (list '(mncexpt) ($binarybfloat (cadr x)) (caddr x)))
346 ((eq (caar x) 'rat)
347 (ratbigfloat (cdr x)))
348 ((setq y (safe-get (caar x) 'floatprog))
349 (funcall y (mapcar #'$binarybfloat (cdr x)))
351 ;; removed stuff here
352 #+ignore
353 ((or (trigp (caar x)) (arcp (caar x)) (eq (caar x) '$entier))
354 (setq y ($binarybfloat (cadr x)))
355 (if ($bfloatp y)
356 (cond ((eq (caar x) '$entier) ($entier y))
357 ((arcp (caar x))
358 (setq y ($binarybfloat (logarc (caar x) y)))
359 (if (free y '$%i)
360 y (let ($ratprint) (fparcsimp ($rectform y)))))
361 ((member (caar x) '(%cot %sec %csc) :test #'eq)
362 (invertbigfloat
363 ($binarybfloat (list (ncons (safe-get (caar x) 'recip)) y))))
364 (t ($binarybfloat (exponentialize (caar x) y))))
365 (subst0 (list (ncons (caar x)) y) x)))
366 (t (recur-apply #'$binarybfloat x)))) ;;
368 ;; works for sin cos atan tan log ... and everything else not explicitly redefined
371 #| (defun decsinbigfloat(f)(let((a(car f)))
372 (sinbigfloat (if (decimalfpp a) (list(decfp2binfp a))f ) )))
373 (defun deccosbigfloat(f)(let((a(car f)))
374 (cosbigfloat (if (decimalfpp a) (list(decfp2binfp a))f ))))
375 (defun decatanbigfloat(f)(let((a(car f)))
376 (atanbigfloat (if (decimalfpp a) (list(decfp2binfp a))f ))))
377 (defun dectanbigfloat(f)(let((a(car f)))
378 (tanbigfloat (if (decimalfpp a) (list(decfp2binfp a))f ))))
379 (defun declogbigfloat(f)(let((a(car f)))
380 (logbigfloat (if (decimalfpp a) (list(decfp2binfp a))f ))))
381 ;(defprop %sin decsinbigfloat floatprog)
382 ;(defprop %cos deccosbigfloat floatprog)
383 ;(defprop %atan decatanbigfloat floatprog)
384 ;(defprop %tan dectanbigfloat floatprog)
385 ;(defprop %log declogbigfloat floatprog)
390 (defun make-decimalfp-prog(j)
391 (let ((k (get j 'floatprog)))
392 ; (format t "~% name ~s has floatprog ~s" j k)
393 (if (and k (symbolp k)) ; nil is a symbol too...
394 (let ((program
395 `(lambda(f)(let ((a (car f)))
396 (,k (if (decimalfpp a) (list(decfp2binfp a))
397 f ))))))
398 (format t "~%redefining bigfloat ~s to also work for decimal bigfloat" j)
399 (setf (get j 'floatprog) (compile nil program))))))
401 (eval-when
402 #+gcl (load eval)
403 #-gcl (:load-toplevel :execute)
404 (do-symbols (j :maxima 'decimal-floats-installed)
405 (unless (member j '(mabs mplus mtimes rat) :test 'eq)
406 (make-decimalfp-prog j))))
408 ;; exceptions to the uniform treatment above...
410 (defun decmabsbigfloat (l)
411 (let* ((a (car l))
412 (r (bigfloatp a)))
413 ;; (format t "~%decmabsbigfloat a=~s r=~s" a r)
414 (cond ((null r) (list '(mabs) a))
415 ((decimalfpp a)
416 (decbcons (list (abs (cadr a))(caddr a))))
417 (t (bcons(fpabs (cdr r))))))) ;; probably never used
419 (defprop mabs decmabsbigfloat floatprog)
421 ;;(defun decrat2fp(f)(bigfloat2rat (car f)))
423 ;;etc
425 (defprop mplus decaddbigfloat floatprog)
426 (defprop mtimes dectimesbigfloat floatprog)
427 (defprop rat decrat2fp floatprog) ; this appears to not be used..
430 (defun decfp2binfp(f) ;convert integer or rational or decimal fp to binary fp
431 (cond((numberp f)($binarybfloat f))
432 ((decimalfpp f) ;check if decimal
433 ($binarybfloat (let((r (* (cadr f)(expt 10 (caddr f)))))
434 (list '(rat) (numerator r)(denominator r)))))
435 (t ($binarybfloat f))))
437 (defun decaddbigfloat (h)
438 ;; h is a list of bigfloats. it will
439 ;; return one bigfloat, maybe decimal
440 ;; if there is at least one binary, convert all to binary.
441 (let ((anybin (some #'binaryfpp h))
442 (r nil)
443 (fans nil))
444 (if (and anybin (some #'decimalfpp h))
445 ;; then there are some of each
446 (setf h (map 'list #'decfp2binfp h)) ; convert everything to binary
447 ;;otherwise everything is decimal or maybe integer??
449 ;; (format t "~% decAddBigFloat h=~s" h)
450 (if anybin ; all are in binary
451 (let ()
452 (setf fans (bcons '(0 0)))
453 (map nil #'(lambda(z)
454 (setf r (bigfloatp z))
455 (setq fans (bcons (fpplus (cdr r)(cdr fans)))))
457 ;; all are decimal
458 (let()
459 (setf fans (decbcons '(0 0)))
460 (map nil #'(lambda(z)
461 (setf r ($bfloat z))
462 (setq fans (decbcons (decfpplus (cdr r)(cdr fans)))))
463 h)))
464 fans))
467 ;; convert a maxima rat to a decimal float. 1/2016
469 ;; for n/d rational number divide(n*10^$fpprec,d) to get [s,r] such that n/d= s/10^fprec+r.
470 ;; e.g. 321/4 .. $fpprec=10, we get [802500000000, 0]
471 ;; so 321/4 is 802500000000 x 10^-10 or 80.25.
472 ;; better would be 8025 x10^-2 .
474 (defun decrat2fp (r) ; r is ((rat) n d)
475 (cond((decimalfpp r) r)
476 ((and (consp r)(eq (caar r) 'rat))
477 (let* ((n (cadr r))
478 (d (caddr r))
479 (expon (+ (flatsize10 d)$fpprec))
480 (shifter (expt 10 expon )))
481 ;; add expon zeros to the numerator, divide by d (actually, truncate) then mult by 10^ expon
482 (decbcons (list (truncate (* n shifter) d) (- expon)))))
483 ((integerp r)
484 (decbcons (list r 0)))
485 (t(decrat2fp ($rationalize r))))) ; other numbers
488 ;; intofp takes any expression and return a bigfloat,
489 ;; decintofp modifies that so that the answer is
490 ;; decimal if possible. %pi is not returned as decimal.
491 ;; Returns a bigfloat with header
492 (defun decintofp (l)
493 (cond ((not (atom l)) ($bfloat l))
494 ((floatp l) (decfloat-from-fp l))
495 ((equal 0 l)(decbcons '(0 0)))
496 ((eq l '$%pi)(bcons (fppi)))
497 ((eq l '$%e) (bcons(fpe)))
498 ((eq l '$%gamma) (bcons(fpgamma)))
499 (t (decbcons (list l 0)))
502 (defun decfpquotient (a b) ; decimal version just a hack
503 (cond ((equal (car b) 0)
504 (merror (intl:gettext "pquotient: attempted quotient by zero.")))
505 ((equal (car a) 0) '(0 0))
506 (t (decimalfptrim (list (truncate (/ (* (expt 10 $fpprec)(car a))
507 (car b)))
508 (- (cadr a)(cadr b) $fpprec ))))))
510 (defun decfpdifference (a b)
511 (fpplus a (fpminus b)))
513 (defun decfpminus (x)
514 (if (equal (car x) 0)
516 (list (- (car x)) (cadr x))))
518 (defun decfpplus(a b)
519 ;; totally without rounding
520 (let ((exp(- (cadr a) (cadr b))))
522 (cond ((= exp 0)(list (+ (car a)(car b)) (cadr a)))
523 ((> exp 0)
524 (list (+ (* (expt 10 exp) (car a))
525 (car b))
526 (cadr b)))
528 (t (list (+ (* (car b)(expt 10 (- exp)))
529 (car a))
530 (cadr a))))))
532 (defun dectimesbigfloat (h)
533 ;; h is a list of bigfloats. it will
534 ;; return one bigfloat, maybe decimal
535 ;; if there is at least one binary, convert all to binary.
536 (let ((anybin (some #'binaryfpp h)) ;anybin is T if there is a binary bigfloat
537 (r nil)
538 (fans nil))
539 (if (and anybin (some #'decimalfpp h))
540 ;; then there are some of each
541 (setf h (map 'list #'decfp2binfp h)) ; some binary and some dec:convert everything to binary
542 ;;otherwise everything is decimal or maybe integer??
544 ;; (format t "~% decTimesBigFloat h=~s,~% anybin=~s" h anybin)
545 (if anybin ; all are in binary
546 (let ()
547 (setf fans (bcons(fpone)))
548 (map nil #'(lambda(z)
549 (setf r (bigfloatp z))
550 (setq fans (bcons (fptimes* (cdr r)(cdr fans)))))
552 ;; all are decimal
553 (let()
555 (setf fans (decbcons '(1 0)))
556 (map nil #'(lambda(z)
557 (setf r ($bfloat z))
558 (setq fans (decbcons (decfptimes (cdr r)(cdr fans)))))
559 h)))
560 fans))
562 (defun decfptimes (a b) (decimalfptrim (decfptimes* a b)))
564 (defun decfptimes* (a b)
565 ;; totally without rounding
566 (list (* (car a)(car b))
567 (+ (cadr a)(cadr b))))
569 ;; Don't use the symbol BASE since it is SPECIAL.
571 (defun decfpintexpt (int nn fixprec) ;INT is integer
572 (setq fixprec (truncate fixprec (1- (integer-length int)))) ;NN is pos
573 (let ((bas (decintofp (expt int (min nn fixprec)))))
574 (if (> nn fixprec)
575 (fptimes* (decintofp (expt int (rem nn fixprec)))
576 (fpexpt bas (quotient nn fixprec)))
577 bas)))
579 ;; NN is positive or negative integer
580 (defun decfpone()'(1 0))
582 ;; this is not yet elaborated on.
583 ;; rewrite modeled on addbigfloat
584 (defun timesbigfloat (h)
585 (prog (fans r nfans)
586 (setq fans (decbcons (fpone)) nfans 1)
587 (do ((l h (cdr l)))
588 ((null l))
589 (if (setq r (bigfloatp (car l)))
590 (setq fans (decbcons (fptimes* (cdr r) (cdr fans))))
591 (setq nfans (list '(mtimes) (car l) nfans))))
592 (return (if (equal nfans 1)
593 fans
594 (simplifya (list '(mtimes) fans nfans) nil)))))
597 (defun invertbigfloat (a) ;works and this has 1/3.0L0 in binary
598 (bcons (fpquotient (fpone) (if (decimalfpp a)
599 (cdr(decfp2binfp a))
600 (cdr a)))))
602 ;;; taken out of nparse.lisp.
603 (defun make-number (data)
604 (setq data (nreverse data))
605 ;; Maxima really wants to read in any number as a flonum
606 ;; (except when we have a bigfloat, of course!). So convert exponent
607 ;; markers to the flonum-exponent-marker.
608 (let ((marker (car (nth 3 data))))
609 (unless (eql marker flonum-exponent-marker)
610 (when (member marker '(#\E #\F #\S #\D #+cmu #\W))
611 (setf (nth 3 data) (list flonum-exponent-marker)))))
612 (cond ((equal (nth 3 data) '(#\B))
613 ;; (format t "~% exponent B data=~s~%" data)
614 (let*
615 ((*read-base* 10.)
616 (int-part (readlist (or (first data) '(#\0))))
617 (frac-part (readlist (or (third data) '(#\0))))
618 (frac-len (length (third data)))
619 (exp-sign (first (fifth data)))
620 (exp (readlist (sixth data))))
621 (if (and $fast_bfloat_conversion
622 (> (abs exp) $fast_bfloat_threshold))
623 ;; Exponent is large enough that we don't want to do exact
624 ;; rational arithmetic. Instead we do bfloat arithmetic.
625 ;; For example, 1.234b1000 is converted by computing
626 ;; bfloat(1234)*10b0^(1000-3). Extra precision is used
627 ;; during the bfloat computations.
628 (let* ((extra-prec (+ *fast-bfloat-extra-bits* (ceiling (log exp 2e0))))
629 (fpprec (+ fpprec extra-prec))
630 (mant (+ (* int-part (expt 10 frac-len)) frac-part))
631 (bf-mant (bcons (intofp mant)))
632 (p (power (bcons (intofp 10))
633 (- (if (char= exp-sign #\-)
634 (- exp)
635 exp)
636 frac-len)))
637 ;; Compute the product using extra precision. This
638 ;; helps to get the last bit correct (but not
639 ;; always). If we didn't do this, then bf-mant and
640 ;; p would be rounded to the target precision and
641 ;; then the product is rounded again. Doing it
642 ;; this way, we still have 3 roundings, but bf-mant
643 ;; and p aren't rounded too soon.
644 (result (mul bf-mant p)))
645 (let ((fpprec (- fpprec extra-prec)))
646 ;; Now round the product back to the desired precision.
647 (bigfloatp result)))
648 ;; For bigfloats, turn them into rational numbers then
649 ;; convert to bigfloat. Fix for the 0.25b0 # 2.5b-1 bug.
650 ;; Richard J. Fateman posted this fix to the Maxima list
651 ;; on 10 October 2005. Without this fix, some tests in
652 ;; rtestrationalize will fail. Used with permission.
653 (let ((ratio (* (+ int-part (* frac-part (expt 10 (- frac-len))))
654 (expt 10 (if (char= exp-sign #\-)
655 (- exp)
656 exp)))))
657 ($binarybfloat (cl-rat-to-maxima ratio))))))
658 ;; decimal input
659 ((equal (nth 3 data) '(#\L))
660 ;; (format t "~% exponent L data=~s~%" data)
661 (let*
662 ((*read-base* 10.)
663 (int-part (readlist (or (first data) '(#\0))))
664 (frac-part (readlist (or (third data) '(#\0))))
665 (frac-len (length (third data)))
666 (exp-sign (first (fifth data)))
667 (exp (readlist (sixth data))))
669 (let* ((bigmant
670 (+ frac-part (* int-part (expt 10 frac-len))))
671 (bigexp (- (if (char= exp-sign #\-)
672 (- exp)
673 exp) frac-len)) )
675 (decbcons (list bigmant bigexp)))))
676 (t (readlist (apply #'append data)))))
679 ;; from maxmin.lisp
681 (defun $rationalize (e)
683 (setq e (ratdisrep e))
684 (cond ((floatp e)
685 (let ((significand) (expon) (sign))
686 (multiple-value-setq (significand expon sign) (integer-decode-float e))
687 (cl-rat-to-maxima (* sign significand (expt 2 expon)))))
689 #+ignore
690 (($bfloatp e) (cl-rat-to-maxima (* (cadr e)(expt 2 (- (caddr e) (third (car e)))))))
691 ((binaryfpp e) (cl-rat-to-maxima (* (cadr e)(expt 2 (- (caddr e) (third (car e)))))))
692 ((decimalfpp e) (cl-rat-to-maxima (* (cadr e)(expt 10 (caddr e)))))
694 (($mapatom e) e)
695 (t (simplify (cons (list (mop e)) (mapcar #'$rationalize (margs e)))))))
697 ;; from trigi
699 (defun big-float-eval (op z)
700 (if (decimalfpp z)(setf z (decfp2binfp z)))
701 (when (complex-number-p z 'bigfloat-or-number-p)
702 (let ((x ($realpart z))
703 (y ($imagpart z))
704 (bop (gethash op *big-float-op*)))
705 (macrolet ((afloatp (u)
706 `(or (floatp ,u) ($bfloatp ,u))))
707 ;; If bop is non-NIL, we want to try that first. If bop
708 ;; declines (by returning NIL), we silently give up and use the
709 ;; rectform version.
710 (cond ((and (afloatp x) (like 0 y))
711 (or (and bop (funcall bop ($bfloat x)))
712 ($bfloat `((,op simp) ,x))))
713 ((or (afloatp x) (afloatp y))
714 (or (and bop (funcall bop ($bfloat x) ($bfloat y)))
715 (let ((z (add ($bfloat x) (mul '$%i ($bfloat y)))))
716 (setq z ($rectform `((,op simp) ,z)))
717 ($bfloat z)))))))))
720 rationalize(1.0b-1)-1/10 ; should be non-zero
721 rationalize(1.0L-1)-1/10 ; ; should be zero
724 (eval-when
725 #+gcl (load eval)
726 #-gcl (:load-toplevel :execute)
727 (fpprec1 nil $fpprec) ; Set up user's precision
730 ;; these 3 functions below are not needed .. see advise-fun-simp
731 ;; for the workaround.
732 #+ignore
733 (defun $decfloor(f)
734 (if (decimalfpp f) (floor (* (cadr f)(expt 10 (caddr f))))
735 (mfuncall '$floor f)))
737 #+ignore
738 (defun $decceiling(f)
739 (if (decimalfpp f)(ceiling (* (cadr f)(expt 10 (caddr f))))
740 (mfuncall '$ceiling f)))
742 #+ignore
743 (defun $dectruncate(f)
744 (if (decimalfpp f)(truncate (* (cadr f)(expt 10 (caddr f))))
745 (mfuncall '$truncate f)))
747 (defun advise-fun-simp (r test var val) ;; hack the simplification
748 (unless (get r 'orig)
749 (setf (get r 'orig) (get r 'operators))) ; get the simplification program
750 (setf (get r 'operators)
751 (compile nil ` (lambda(,var %x %y)(declare(ignore %x %y))
752 (if ,test ,val (,(get r 'orig) ,var 1 t))))))
753 ;; sort of like tellsimp
754 (advise-fun-simp '%truncate '(decimalfpp (cadr f)) 'f '(truncate (* (cadadr f)(expt 10 (caddr(cadr f))))))
755 (advise-fun-simp '$floor '(decimalfpp (cadr f)) 'f '(floor (* (cadadr f) (expt 10 (caddr(cadr f))))))
756 (advise-fun-simp '$ceiling '(decimalfpp (cadr f)) 'f '(ceiling (* (cadadr f) (expt 10 (caddr(cadr f))))))
757 ;; why $floor but %truncate? historical accident..
759 ;; $remainder is a function... another inconsistency..
761 (defvar *oldremainder (symbol-function '$remainder))
763 (defun $remainder (x y) ;; convert to rational? remainder is always 0 in Rational Field
764 (if (decimalfpp x)(setf x (bigfloat2rat x)))
765 (if (decimalfpp y)(setf y (bigfloat2rat y)))
766 ; (format t "~% x=~s y=~s" x y) test
767 (funcall *oldremainder x y))
769 (defun $decimalfpp(x)(if (decimalfpp x) t nil))
774 (in-package :bigfloat)
775 ;; from numeric.lisp
776 ;; which uses structures for bigfloats, including complex
777 ;; stuff that did not exist when the float.lisp stuff was written c. 1974
779 (defun bigfloat (re &optional im)
780 "Convert RE to a BIGFLOAT. If IM is given, return a COMPLEX-BIGFLOAT"
781 (if (maxima::decimalfpp re)(setf re (maxima::decfp2binfp re))) ;added rjf
782 (if (maxima::decimalfpp im)(setf im (maxima::decfp2binfp im))) ;added rjf
783 (cond (im
784 (make-instance 'complex-bigfloat
785 :real (intofp re)
787 :imag (intofp im)))
788 ((cl:realp re)
789 (make-instance 'bigfloat :real (intofp re)))
790 ((cl:complexp re)
791 (make-instance 'complex-bigfloat
792 :real (intofp (cl:realpart re))
793 :imag (intofp (cl:imagpart re))))
794 ((maxima::$bfloatp re)
796 (make-instance 'bigfloat :real re )) ;new
798 ((maxima::complex-number-p re 'maxima::bigfloat-or-number-p)
799 (make-instance 'complex-bigfloat
800 :real (maxima::decfp2binfp (maxima::$realpart re))
801 :imag (maxima::decfp2binfp (maxima::$imagpart re))
803 ((typep re 'bigfloat)
804 ;; Done this way so the new bigfloat updates the precision of
805 ;; the given bigfloat, if necessary.
806 (make-instance 'bigfloat :real (real-value re)))
807 ((typep re 'complex-bigfloat)
808 ;; Done this way so the new bigfloat updates the precision of
809 ;; the given bigfloat, if necessary.
810 (make-instance 'complex-bigfloat
811 :real (real-value re)
812 :imag (imag-value re)))
814 (make-instance 'bigfloat :real (maxima::decimalfpp re)))))
818 #| BUGS 3/19/2016 abs(2.0l0) comes out as binary. eh. hard to fix because
819 bigfloat-impl::bigfloat loses the radix.
820 atan2(3,4.0l0) wrong. where to patch??
821 remainder (6.1L0,6)
823 atan2(3.0l0,4) works