1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
4 (declare-top (special *m fpprec $fpprec $float $bfloat $ratprint $ratepsilon $domain $m1pbranch
5 $rounddecimalfloats machine-mantiss-precision
))
7 (defvar $rounddecimalfloats nil
)
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
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.
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
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)
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
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!
69 (defun decimalround (s e ad
) ; we want to remove ad digits from the right
70 (let*((guard 0) ; this is the guard digit
72 ;significand with one extra (guard) digit
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.
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.
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
106 ;;; i.e. sign=-1, because sign=0 can't happen
107 (cond ((> guard
5) (truncate swithguard
10))
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
118 (defun flatsize10(r) (if (= r
0) 1
119 (ceiling (* #.
(log 2)(integer-length (abs r
))) #.
(log 10 ))))
123 ;; *DECFP = T if the computation is being done in decimal radix. NIL implies
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
159 ;; uses L marker instead of b. 123b0 prints 1.23L2
161 (defun decfpformat (l)
163 (cond ((= (cadr l
) 0) '(|
0| |.| |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
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
179 ;; overwrites the standard bigfloatp
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
187 (cond ((not ($bfloatp x
)) (return nil
))
188 ((= fpprec
(caddar x
))
189 ;; Precision matches. (Should we fix up bogus bigfloat
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
)))
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
)))
212 (setq x
(bigfloatp x
))
217 (setq exp
(cond ((minusp (cadr x
))
219 y
(fpration1 (cons (car x
) (fpabs (cdr x
)))))
220 (rplaca y
(* -
1 (car y
))))
223 (princ "`rat' replaced ")
224 (when sign
(princ "-"))
225 (princ (maknam (fpformat (cons (car x
) (fpabs (cdr x
))))))
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
))))))
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
247 (coerce (* (cadr l
)(expt 10 (caddr l
))) 'double-float
)
248 (let ((precision (caddar l
))
251 (fpprec machine-mantissa-precision
)
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
)))
266 (merror (intl:gettext
"float: floating point overflow converting ~:M") l
)
267 (scale-float mantissa e
))))
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
279 ((bigfloatp x
)) ; return x, possibly changed precision
280 ((numberp x
) ;; favors decimal conversion for CL numbers
283 ((numberp x
) ;; favors binary conversion for CL numbers
285 ((atom x
)($binarybfloat x
)) ; %pi, %phi
288 ((and(eq (caar x
) 'mexpt
)
289 (decimalfpp (cadr x
))
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)
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
312 ((atom x
)($binarybfloat x
)) ; %pi, %phi
315 ((and(eq (caar x
) 'mexpt
)
316 (decimalfpp (cadr x
))
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
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
)
332 (member x
'($%e $%pi $%gamma
) :test
#'eq
))
334 ((or (atom x
) (member 'array
(cdar x
) :test
#'eq
))
336 ($binarybfloat
'((mtimes simp
)
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
)))
347 (ratbigfloat (cdr x
)))
348 ((setq y
(safe-get (caar x
) 'floatprog
))
349 (funcall y
(mapcar #'$binarybfloat
(cdr x
)))
351 ;; removed stuff here
353 ((or (trigp (caar x
)) (arcp (caar x
)) (eq (caar x
) '$entier
))
354 (setq y
($binarybfloat
(cadr x
)))
356 (cond ((eq (caar x
) '$entier
) ($entier y
))
358 (setq y
($binarybfloat
(logarc (caar x
) y
)))
360 y
(let ($ratprint
) (fparcsimp ($rectform y
)))))
361 ((member (caar x
) '(%cot %sec %csc
) :test
#'eq
)
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...
395 `(lambda(f)(let ((a (car f
)))
396 (,k
(if (decimalfpp a
) (list(decfp2binfp a
))
398 (format t
"~%redefining bigfloat ~s to also work for decimal bigfloat" j
)
399 (setf (get j
'floatprog
) (compile nil program
))))))
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)
413 ;; (format t "~%decmabsbigfloat a=~s r=~s" a r)
414 (cond ((null r
) (list '(mabs) 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)))
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
))
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
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
)))))
459 (setf fans
(decbcons '(0 0)))
460 (map nil
#'(lambda(z)
462 (setq fans
(decbcons (decfpplus (cdr r
)(cdr 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
))
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
)))))
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
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
))
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
)))
524 (list (+ (* (expt 10 exp
) (car a
))
528 (t (list (+ (* (car b
)(expt 10 (- exp
)))
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
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
547 (setf fans
(bcons(fpone)))
548 (map nil
#'(lambda(z)
549 (setf r
(bigfloatp z
))
550 (setq fans
(bcons (fptimes* (cdr r
)(cdr fans
)))))
555 (setf fans
(decbcons '(1 0)))
556 (map nil
#'(lambda(z)
558 (setq fans
(decbcons (decfptimes (cdr r
)(cdr 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
)))))
575 (fptimes* (decintofp (expt int
(rem nn fixprec
)))
576 (fpexpt bas
(quotient nn fixprec
)))
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)
586 (setq fans
(decbcons (fpone)) nfans
1)
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)
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
)
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)
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
#\-
)
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.
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
#\-
)
657 ($binarybfloat
(cl-rat-to-maxima ratio
))))))
659 ((equal (nth 3 data
) '(#\L
))
660 ;; (format t "~% exponent L data=~s~%" data)
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
))))
670 (+ frac-part
(* int-part
(expt 10 frac-len
))))
671 (bigexp (- (if (char= exp-sign
#\-
)
675 (decbcons (list bigmant bigexp
)))))
676 (t (readlist (apply #'append data
)))))
681 (defun $rationalize
(e)
683 (setq e
(ratdisrep 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
)))))
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
)))))
695 (t (simplify (cons (list (mop e
)) (mapcar #'$rationalize
(margs e
)))))))
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
))
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
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
)))
720 rationalize
(1.0b-1
)-
1/10 ; should be non-zero
721 rationalize
(1.0L-1
)-
1/10 ; ; should be zero
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.
734 (if (decimalfpp f
) (floor (* (cadr f
)(expt 10 (caddr f
))))
735 (mfuncall '$floor f
)))
738 (defun $decceiling
(f)
739 (if (decimalfpp f
)(ceiling (* (cadr f
)(expt 10 (caddr f
))))
740 (mfuncall '$ceiling f
)))
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
)
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
784 (make-instance 'complex-bigfloat
789 (make-instance 'bigfloat
:real
(intofp 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??