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 (defmfun $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. 123L0 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 #+gcl
(declare (notinline write-char
))
210 (if (decimalfpp x
) (let ((k (* (cadr x
)(expt 10 (caddr x
)))))
211 (list '(rat) (numerator k
)(denominator k
)))
213 (setq x
(bigfloatp x
))
218 (setq exp
(cond ((minusp (cadr x
))
220 y
(fpration1 (cons (car x
) (fpabs (cdr x
)))))
221 (rplaca y
(* -
1 (car y
))))
224 (princ "`rat' replaced ")
225 (when sign
(princ "-"))
226 (princ (maknam (fpformat (cons (car x
) (fpabs (cdr x
))))))
232 (setq x
($bfloat
(list '(rat simp
) (car exp
) (cdr exp
))))
233 (when sign
(princ "-"))
234 (princ (maknam (fpformat (cons (car x
) (fpabs (cdr x
))))))
238 ;; Convert a machine floating point number into a bigfloat.
239 ;; Since it is a binary float, no point in making it decimal..
240 ;; Probably we don't do this a lot, so we just do it
241 ;; with a short program.
242 (defun decfloat-from-fp (x) ($binarybfloat
($rationalize x
)))
244 ;; Convert a bigfloat into a floating point number.
245 (defun fp2flo(l)(decfp2flo l
)) ; redefine usual
248 (coerce (* (cadr l
)(expt 10 (caddr l
))) 'double-float
)
249 (let ((precision (caddar l
))
252 (fpprec machine-mantissa-precision
)
254 ;; Round the mantissa to the number of bits of precision of the
255 ;; machine, and then convert it to a floating point fraction. We
256 ;; have 0.5 <= mantissa < 1
257 (setq mantissa
(quotient (fpround mantissa
) (expt 2.0 machine-mantissa-precision
)))
258 ;; Multiply the mantissa by the exponent portion. I'm not sure
259 ;; why the exponent computation is so complicated.
261 ;; GCL doesn't signal overflow from scale-float if the number
262 ;; would overflow. We have to do it this way. 0.5 <= mantissa <
263 ;; 1. The largest double-float is .999999 * 2^1024. So if the
264 ;; exponent is 1025 or higher, we have an overflow.
265 (let ((e (+ exponent
(- precision
) *m machine-mantissa-precision
)))
267 (merror (intl:gettext
"float: floating point overflow converting ~:M") l
)
268 (scale-float mantissa e
))))
272 `((bigfloat simp
,$fpprec decimal
) .
,(decimalfptrim s
)))
274 ;; probably not useful. We only allow new decimal bigfloats
275 ;; if they are typed in as 1.2L0 etc Or maybe if they are integers??
278 (defmfun $bfloat
(x) ;; used by too many other programs. need to replace it here
280 ((bigfloatp x
)) ; return x, possibly changed precision
281 ((numberp x
) ;; favors decimal conversion for CL numbers
284 ((numberp x
) ;; favors binary conversion for CL numbers
286 ((atom x
)($binarybfloat x
)) ; %pi, %phi
289 ((and(eq (caar x
) 'mexpt
)
290 (decimalfpp (cadr x
))
293 (decfppower (cadr x
)(caddr x
))) ; float^integer
295 ((eq (caar x
) 'mtimes
)
296 (dectimesbigfloat (mapcar #'$decbfloat
(cdr x
)))) ;; not enough.?
298 ((eq (caar x
) 'mplus
)
299 (decaddbigfloat (mapcar #'$decbfloat
(cdr x
))))
301 ;; here we return to the previous program
302 (t ($binarybfloat x
))))
304 (defmfun $decbfloat
(x)
307 (if (null $rounddecimalfloats
) x
; just return it
308 (decbcons (decimalfptrim (cdr x
))))); possibly chop/round it
311 ((numberp x
) ;; favors decimal conversion for CL numbers
313 ((atom x
)($binarybfloat x
)) ; %pi, %phi
316 ((and(eq (caar x
) 'mexpt
)
317 (decimalfpp (cadr x
))
320 (decfppower (cadr x
)(caddr x
))) ; float^integer
321 ;; here we return to the previous program
323 (t ($binarybfloat x
))))
325 (defun decfppower (ba e
) ;ba^e, e is nonneg int
328 (dotimes (i e
(decbcons (decimalfptrim ans
))) (setf ans
(decfptimes ans b
)))))
330 (defmfun $binarybfloat
(x &aux
(y nil
))
331 (cond ((setf y
(bigfloatp x
)) y
)
333 (member x
'($%e $%pi $%gamma
) :test
#'eq
))
335 ((or (atom x
) (member 'array
(cdar x
) :test
#'eq
))
337 ($binarybfloat
'((mtimes simp
)
339 ((mplus simp
) 1 ((mexpt simp
) 5 ((rat simp
) 1 2)))))
341 ((eq (caar x
) 'mexpt
)
342 (if (equal (cadr x
) '$%e
)
343 (*fpexp
(decfp2binfp (caddr x
))) ;; exp(x)
344 (exptbigfloat (decfp2binfp (cadr x
))
346 ;;(decfp2binfp(caddr x))
348 ((eq (caar x
) 'mncexpt
)
349 (list '(mncexpt) ($binarybfloat
(cadr x
)) (caddr x
)))
351 (ratbigfloat (cdr x
)))
352 ((setq y
(safe-get (caar x
) 'floatprog
))
353 (funcall y
(mapcar #'$binarybfloat
(cdr x
)))
355 ;; removed stuff here
357 ((or (trigp (caar x
)) (arcp (caar x
)) (eq (caar x
) '$entier
))
358 (setq y
($binarybfloat
(cadr x
)))
360 (cond ((eq (caar x
) '$entier
) ($entier y
))
362 (setq y
($binarybfloat
(logarc (caar x
) y
)))
364 y
(let ($ratprint
) (fparcsimp ($rectform y
)))))
365 ((member (caar x
) '(%cot %sec %csc
) :test
#'eq
)
367 ($binarybfloat
(list (ncons (safe-get (caar x
) 'recip
)) y
))))
368 (t ($binarybfloat
(exponentialize (caar x
) y
))))
369 (subst0 (list (ncons (caar x
)) y
) x
)))
370 (t (recur-apply #'$binarybfloat x
)))) ;;
372 (defun bigfloat-prec(z)(third(car z
))) ;; assume ((bigfloat simp #)..) or (bigfloat simp # decimal) ...)
374 ;; works for sin cos atan tan log ... and everything else not explicitly redefined
377 #|
(defun decsinbigfloat(f)(let((a(car f
)))
378 (sinbigfloat (if (decimalfpp a
) (list(decfp2binfp a
))f
) )))
379 (defun deccosbigfloat(f)(let((a(car f
)))
380 (cosbigfloat (if (decimalfpp a
) (list(decfp2binfp a
))f
))))
381 (defun decatanbigfloat(f)(let((a(car f
)))
382 (atanbigfloat (if (decimalfpp a
) (list(decfp2binfp a
))f
))))
383 (defun dectanbigfloat(f)(let((a(car f
)))
384 (tanbigfloat (if (decimalfpp a
) (list(decfp2binfp a
))f
))))
385 (defun declogbigfloat(f)(let((a(car f
)))
386 (logbigfloat (if (decimalfpp a
) (list(decfp2binfp a
))f
))))
387 ;(defprop %sin decsinbigfloat floatprog)
388 ;(defprop %cos deccosbigfloat floatprog)
389 ;(defprop %atan decatanbigfloat floatprog)
390 ;(defprop %tan dectanbigfloat floatprog)
391 ;(defprop %log declogbigfloat floatprog)
396 (defun make-decimalfp-prog(j)
397 (let ((k (get j
'floatprog
)))
398 ; (format t "~% name ~s has floatprog ~s" j k)
399 (if (and k
(symbolp k
)) ; nil is a symbol too...
401 `(lambda(f)(let ((a (car f
)))
402 (,k
(if (decimalfpp a
) (list(decfp2binfp a
))
404 (format t
"~%redefining bigfloat ~s to also work for decimal bigfloat" j
)
405 (setf (get j
'floatprog
) (compile nil program
))))))
408 (:load-toplevel
:execute
)
409 (do-symbols (j :maxima
'decimal-floats-installed
)
410 (unless (member j
'(mabs mplus mtimes rat
) :test
'eq
)
411 (make-decimalfp-prog j
))))
413 ;; exceptions to the uniform treatment above...
415 (defun decmabsbigfloat (l)
418 ;; (format t "~%decmabsbigfloat a=~s r=~s" a r)
419 (cond ((null r
) (list '(mabs) a
))
421 (decbcons (list (abs (cadr a
))(caddr a
))))
422 (t (bcons(fpabs (cdr r
))))))) ;; probably never used
424 (defprop mabs decmabsbigfloat floatprog
)
426 ;;(defun decrat2fp(f)(bigfloat2rat (car f)))
430 (defprop mplus decaddbigfloat floatprog
)
431 (defprop mtimes dectimesbigfloat floatprog
)
432 (defprop rat decrat2fp floatprog
) ; this appears to not be used..
435 (defun decfp2binfp(f) ;convert integer or rational or decimal fp to binary fp
436 (cond((numberp f
)($binarybfloat f
))
437 ((decimalfpp f
) ;check if decimal
438 ($binarybfloat
(let((r (* (cadr f
)(expt 10 (caddr f
)))))
439 (list '(rat) (numerator r
)(denominator r
)))))
440 (t ($binarybfloat f
))))
442 (defun decaddbigfloat (h)
443 ;; h is a list of bigfloats. it will
444 ;; return one bigfloat, maybe decimal
445 ;; if there is at least one binary, convert all to binary.
446 (let ((anybin (some #'binaryfpp h
))
449 (if (and anybin
(some #'decimalfpp h
))
450 ;; then there are some of each
451 (setf h
(map 'list
#'decfp2binfp h
)) ; convert everything to binary
452 ;;otherwise everything is decimal or maybe integer??
454 ;; (format t "~% decAddBigFloat h=~s" h)
455 (if anybin
; all are in binary
457 (setf fans
(bcons '(0 0)))
458 (map nil
#'(lambda(z)
459 (setf r
(bigfloatp z
))
460 (setq fans
(bcons (fpplus (cdr r
)(cdr fans
)))))
464 (setf fans
(decbcons '(0 0)))
465 (map nil
#'(lambda(z)
467 (setq fans
(decbcons (decfpplus (cdr r
)(cdr fans
)))))
472 ;; convert a maxima rat to a decimal float. 1/2016
474 ;; for n/d rational number divide(n*10^$fpprec,d) to get [s,r] such that n/d= s/10^fprec+r.
475 ;; e.g. 321/4 .. $fpprec=10, we get [802500000000, 0]
476 ;; so 321/4 is 802500000000 x 10^-10 or 80.25.
477 ;; better would be 8025 x10^-2 .
479 (defun decrat2fp (r) ; r is ((rat) n d)
480 (cond((decimalfpp r
) r
)
481 ((and (consp r
)(eq (caar r
) 'rat
))
484 (expon (+ (flatsize10 d
)$fpprec
))
485 (shifter (expt 10 expon
)))
486 ;; add expon zeros to the numerator, divide by d (actually, truncate) then mult by 10^ expon
487 (decbcons (list (truncate (* n shifter
) d
) (- expon
)))))
489 (decbcons (list r
0)))
490 (t(decrat2fp ($rationalize r
))))) ; other numbers
493 ;; intofp takes any expression and return a bigfloat,
494 ;; decintofp modifies that so that the answer is
495 ;; decimal if possible. %pi is not returned as decimal.
496 ;; Returns a bigfloat with header
498 (cond ((not (atom l
)) ($bfloat l
))
499 ((floatp l
) (decfloat-from-fp l
))
500 ((equal 0 l
)(decbcons '(0 0)))
501 ((eq l
'$%pi
)(bcons (fppi)))
502 ((eq l
'$%e
) (bcons(fpe)))
503 ((eq l
'$%gamma
) (bcons(fpgamma)))
504 (t (decbcons (list l
0)))
507 (defun decfpquotient (a b
) ; decimal version just a hack
508 (cond ((equal (car b
) 0)
509 (merror (intl:gettext
"pquotient: attempted quotient by zero.")))
510 ((equal (car a
) 0) '(0 0))
511 (t (decimalfptrim (list (truncate (/ (* (expt 10 $fpprec
)(car a
))
513 (- (cadr a
)(cadr b
) $fpprec
))))))
515 (defun decfpdifference (a b
)
516 (fpplus a
(fpminus b
)))
518 (defun decfpminus (x)
519 (if (equal (car x
) 0)
521 (list (- (car x
)) (cadr x
))))
523 (defun decfpplus(a b
)
524 ;; totally without rounding
525 (let ((exp(- (cadr a
) (cadr b
))))
527 (cond ((= exp
0)(list (+ (car a
)(car b
)) (cadr a
)))
529 (list (+ (* (expt 10 exp
) (car a
))
533 (t (list (+ (* (car b
)(expt 10 (- exp
)))
537 (defun dectimesbigfloat (h)
538 ;; h is a list of bigfloats. it will
539 ;; return one bigfloat, maybe decimal
540 ;; if there is at least one binary, convert all to binary.
541 (let ((anybin (some #'binaryfpp h
)) ;anybin is T if there is a binary bigfloat
544 (if (and anybin
(some #'decimalfpp h
))
545 ;; then there are some of each
546 (setf h
(map 'list
#'decfp2binfp h
)) ; some binary and some dec:convert everything to binary
547 ;;otherwise everything is decimal or maybe integer??
549 ;; (format t "~% decTimesBigFloat h=~s,~% anybin=~s" h anybin)
550 (if anybin
; all are in binary
552 (setf fans
(bcons(fpone)))
553 (map nil
#'(lambda(z)
554 (setf r
(bigfloatp z
))
555 (setq fans
(bcons (fptimes* (cdr r
)(cdr fans
)))))
560 (setf fans
(decbcons '(1 0)))
561 (map nil
#'(lambda(z)
563 (setq fans
(decbcons (decfptimes (cdr r
)(cdr fans
)))))
567 (defun decfptimes (a b
) (decimalfptrim (decfptimes* a b
)))
569 (defun decfptimes* (a b
)
570 ;; totally without rounding
571 (list (* (car a
)(car b
))
572 (+ (cadr a
)(cadr b
))))
574 ;; Don't use the symbol BASE since it is SPECIAL.
576 (defun decfpintexpt (int nn fixprec
) ;INT is integer
577 (setq fixprec
(truncate fixprec
(1- (integer-length int
)))) ;NN is pos
578 (let ((bas (decintofp (expt int
(min nn fixprec
)))))
580 (fptimes* (decintofp (expt int
(rem nn fixprec
)))
581 (fpexpt bas
(quotient nn fixprec
)))
584 ;; NN is positive or negative integer
585 (defun decfpone()'(1 0))
587 ;; this is not yet elaborated on.
588 ;; rewrite modeled on addbigfloat
589 (defun timesbigfloat (h)
591 (setq fans
(decbcons (fpone)) nfans
1)
594 (if (setq r
(bigfloatp (car l
)))
595 (setq fans
(decbcons (fptimes* (cdr r
) (cdr fans
))))
596 (setq nfans
(list '(mtimes) (car l
) nfans
))))
597 (return (if (equal nfans
1)
599 (simplifya (list '(mtimes) fans nfans
) nil
)))))
602 (defun invertbigfloat (a) ;works and this has 1/3.0L0 in binary
603 (bcons (fpquotient (fpone) (if (decimalfpp a
)
607 ;;; taken out of nparse.lisp.
609 #| there is something broken in GCL Maxima.
123L0 says
"incorrect syntax"
611 (defun scan-number-exponent (data)
612 (push (ncons (if (or (char= (parse-tyipeek) #\
+)
613 (char= (parse-tyipeek) #\-
))
617 (scan-digits data
() () t
))
618 (defun scan-number-after-dot (data)
619 (scan-digits data
'(#\E
#\e
#\F
#\f #\B
#\b #\D
#\d
#\S
#\s
621 #+cmu
#\W
#+cmu
#\w
) #'scan-number-exponent
))
623 (defun scan-number-before-dot (data)
624 (scan-digits data
'(#\.
#\E
#\e
#\F
#\f #\B
#\b #\D
#\d
#\S
#\s
629 (defun make-number (data)
630 (setq data
(nreverse data
))
631 ;; Maxima really wants to read in any number as a flonum
632 ;; (except when we have a bigfloat, of course!). So convert exponent
633 ;; markers to the flonum-exponent-marker.
634 (let ((marker (car (nth 3 data
))))
635 (unless (eql marker
+flonum-exponent-marker
+)
638 (member marker
'(#\E
#\F
#\S
#\D
#\L
#\l
#+cmu
#\W
)) ; breaks decimal fp
639 (member marker
'(#\E
#\F
#\S
#\D
#+cmu
#\W
))
640 (setf (nth 3 data
) (list +flonum-exponent-marker
+)))))
644 ((equal (nth 3 data
) '(#\B
))
645 ;; (format t "~% exponent B data=~s~%" data)
648 (int-part (readlist (or (first data
) '(#\
0))))
649 (frac-part (readlist (or (third data
) '(#\
0))))
650 (frac-len (length (third data
)))
651 (exp-sign (first (fifth data
)))
652 (exp (readlist (sixth data
))))
653 (if (and $fast_bfloat_conversion
654 (> (abs exp
) $fast_bfloat_threshold
))
655 ;; Exponent is large enough that we don't want to do exact
656 ;; rational arithmetic. Instead we do bfloat arithmetic.
657 ;; For example, 1.234b1000 is converted by computing
658 ;; bfloat(1234)*10b0^(1000-3). Extra precision is used
659 ;; during the bfloat computations.
660 (let* ((extra-prec (+ *fast-bfloat-extra-bits
* (ceiling (log exp
2e0
))))
661 (fpprec (+ fpprec extra-prec
))
662 (mant (+ (* int-part
(expt 10 frac-len
)) frac-part
))
663 (bf-mant (bcons (intofp mant
)))
664 (p (power (bcons (intofp 10))
665 (- (if (char= exp-sign
#\-
)
669 ;; Compute the product using extra precision. This
670 ;; helps to get the last bit correct (but not
671 ;; always). If we didn't do this, then bf-mant and
672 ;; p would be rounded to the target precision and
673 ;; then the product is rounded again. Doing it
674 ;; this way, we still have 3 roundings, but bf-mant
675 ;; and p aren't rounded too soon.
676 (result (mul bf-mant p
)))
677 (let ((fpprec (- fpprec extra-prec
)))
678 ;; Now round the product back to the desired precision.
680 ;; For bigfloats, turn them into rational numbers then
681 ;; convert to bigfloat. Fix for the 0.25b0 # 2.5b-1 bug.
682 ;; Richard J. Fateman posted this fix to the Maxima list
683 ;; on 10 October 2005. Without this fix, some tests in
684 ;; rtestrationalize will fail. Used with permission.
685 (let ((ratio (* (+ int-part
(* frac-part
(expt 10 (- frac-len
))))
686 (expt 10 (if (char= exp-sign
#\-
)
689 ($binarybfloat
(cl-rat-to-maxima ratio
))))))
691 ((equal (nth 3 data
) '(#\L
))
692 ;; (format t "~% exponent L data=~s~%" data)
695 (int-part (readlist (or (first data
) '(#\
0))))
696 (frac-part (readlist (or (third data
) '(#\
0))))
697 (frac-len (length (third data
)))
698 (exp-sign (first (fifth data
)))
699 (exp (readlist (sixth data
))))
702 (+ frac-part
(* int-part
(expt 10 frac-len
))))
703 (bigexp (- (if (char= exp-sign
#\-
)
707 (decbcons (list bigmant bigexp
)))))
708 (t (readlist (apply #'append data
)))))
713 (defmfun $rationalize
(e)
715 (setq e
(ratdisrep e
))
717 (let ((significand) (expon) (sign))
718 (multiple-value-setq (significand expon sign
) (integer-decode-float e
))
719 (cl-rat-to-maxima (* sign significand
(expt 2 expon
)))))
722 (($bfloatp e
) (cl-rat-to-maxima (* (cadr e
)(expt 2 (- (caddr e
) (third (car e
)))))))
723 ((binaryfpp e
) (cl-rat-to-maxima (* (cadr e
)(expt 2 (- (caddr e
) (third (car e
)))))))
724 ((decimalfpp e
) (cl-rat-to-maxima (* (cadr e
)(expt 10 (caddr e
)))))
727 (t (simplify (cons (list (mop e
)) (mapcar #'$rationalize
(margs e
)))))))
731 (defun big-float-eval (op z
)
732 (if (decimalfpp z
)(setf z
(decfp2binfp z
)))
733 (when (complex-number-p z
'bigfloat-or-number-p
)
734 (let ((x ($realpart z
))
736 (bop (gethash op
*big-float-op
*)))
737 (macrolet ((afloatp (u)
738 `(or (floatp ,u
) ($bfloatp
,u
))))
739 ;; If bop is non-NIL, we want to try that first. If bop
740 ;; declines (by returning NIL), we silently give up and use the
742 (cond ((and (afloatp x
) (like 0 y
))
743 (or (and bop
(funcall bop
($bfloat x
)))
744 ($bfloat
`((,op simp
) ,x
))))
745 ((or (afloatp x
) (afloatp y
))
746 (or (and bop
(funcall bop
($bfloat x
) ($bfloat y
)))
747 (let ((z (add ($bfloat x
) (mul '$%i
($bfloat y
)))))
748 (setq z
($rectform
`((,op simp
) ,z
)))
752 rationalize
(1.0b-1
)-
1/10 ; should be non-zero
753 rationalize
(1.0L-1
)-
1/10 ; ; should be zero
757 (:load-toplevel
:execute
)
758 (fpprec1 nil $fpprec
)) ; Set up user's precision
760 ;; these 3 functions below are not needed .. see advise-fun-simp
761 ;; for the workaround.
763 (defmfun $decfloor
(f)
764 (if (decimalfpp f
) (floor (* (cadr f
)(expt 10 (caddr f
))))
765 (mfuncall '$floor f
)))
768 (defmfun $decceiling
(f)
769 (if (decimalfpp f
)(ceiling (* (cadr f
)(expt 10 (caddr f
))))
770 (mfuncall '$ceiling f
)))
773 (defmfun $dectruncate
(f)
774 (if (decimalfpp f
)(truncate (* (cadr f
)(expt 10 (caddr f
))))
775 (mfuncall '$truncate f
)))
777 (defun advise-fun-simp (r test var val
) ;; hack the simplification
778 (unless (get r
'orig
)
779 (setf (get r
'orig
) (get r
'operators
))) ; get the simplification program
780 (setf (get r
'operators
)
781 (compile nil
` (lambda(,var %x %y
)(declare(ignore %x %y
))
782 (if ,test
,val
(,(get r
'orig
) ,var
1 t
))))))
783 ;; sort of like tellsimp
784 (advise-fun-simp '%truncate
'(decimalfpp (cadr f
)) 'f
'(truncate (* (cadadr f
)(expt 10 (caddr(cadr f
))))))
785 (advise-fun-simp '$floor
'(decimalfpp (cadr f
)) 'f
'(floor (* (cadadr f
) (expt 10 (caddr(cadr f
))))))
786 (advise-fun-simp '$ceiling
'(decimalfpp (cadr f
)) 'f
'(ceiling (* (cadadr f
) (expt 10 (caddr(cadr f
))))))
787 ;; why $floor but %truncate? historical accident..
789 ;; $remainder is a function... another inconsistency..
791 (defvar *oldremainder
(symbol-function '$remainder
))
793 (defmfun $remainder
(x y
) ;; convert to rational? remainder is always 0 in Rational Field
794 (if (decimalfpp x
)(setf x
(bigfloat2rat x
)))
795 (if (decimalfpp y
)(setf y
(bigfloat2rat y
)))
796 ; (format t "~% x=~s y=~s" x y) test
797 (funcall *oldremainder x y
))
799 (defmfun $decimalfpp
(x)(if (decimalfpp x
) t nil
))
804 (in-package :bigfloat
)
806 ;; which uses structures for bigfloats, including complex
807 ;; stuff that did not exist when the float.lisp stuff was written c. 1974
809 (defun bigfloat (re &optional im
)
810 "Convert RE to a BIGFLOAT. If IM is given, return a COMPLEX-BIGFLOAT"
811 (if (maxima::decimalfpp re
)(setf re
(maxima::decfp2binfp re
))) ;added rjf
812 (if (maxima::decimalfpp im
)(setf im
(maxima::decfp2binfp im
))) ;added rjf
814 (make-instance 'complex-bigfloat
819 (make-instance 'bigfloat
:real
(intofp re
)))
821 (make-instance 'complex-bigfloat
822 :real
(intofp (cl:realpart re
))
823 :imag
(intofp (cl:imagpart re
))))
824 ((maxima::$bfloatp re
)
826 (make-instance 'bigfloat
:real re
)) ;new
828 ((maxima::complex-number-p re
'maxima
::bigfloat-or-number-p
)
829 (make-instance 'complex-bigfloat
830 :real
(maxima::decfp2binfp
(maxima::$realpart re
))
831 :imag
(maxima::decfp2binfp
(maxima::$imagpart re
))
833 ((typep re
'bigfloat
)
834 ;; Done this way so the new bigfloat updates the precision of
835 ;; the given bigfloat, if necessary.
836 (make-instance 'bigfloat
:real
(real-value re
)))
837 ((typep re
'complex-bigfloat
)
838 ;; Done this way so the new bigfloat updates the precision of
839 ;; the given bigfloat, if necessary.
840 (make-instance 'complex-bigfloat
841 :real
(real-value re
)
842 :imag
(imag-value re
)))
844 (make-instance 'bigfloat
:real
(maxima::decimalfpp re
)))))
848 #| BUGS
3/19/2016 abs
(2.0l0
) comes out as binary. eh. hard to fix because
849 bigfloat-impl
::bigfloat loses the radix.
850 atan2
(3,4.0l0) wrong. where to patch??