Fix typo
[maxima.git] / share / numeric / decfp-core.lisp
blob33b10d7f49e21a5c13df5e4448639351d0169ebd
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 (defmfun $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. 123L0 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 #+gcl(declare (notinline write-char))
210 (if (decimalfpp x) (let ((k (* (cadr x)(expt 10 (caddr x)))))
211 (list '(rat) (numerator k)(denominator k)))
212 (let ()
213 (setq x (bigfloatp x))
214 (let (($float2bf t)
215 (exp nil)
216 (y nil)
217 (sign nil))
218 (setq exp (cond ((minusp (cadr x))
219 (setq sign t
220 y (fpration1 (cons (car x) (fpabs (cdr x)))))
221 (rplaca y (* -1 (car y))))
222 (t (fpration1 x))))
223 (when $ratprint
224 (princ "`rat' replaced ")
225 (when sign (princ "-"))
226 (princ (maknam (fpformat (cons (car x) (fpabs (cdr x))))))
227 (princ " by ")
228 (princ (car exp))
229 (write-char #\/)
230 (princ (cdr exp))
231 (princ " = ")
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))))))
235 (terpri))
236 exp))))
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
246 (defun decfp2flo (l)
247 (if (decimalfpp l)
248 (coerce (* (cadr l)(expt 10 (caddr l))) 'double-float)
249 (let ((precision (caddar l))
250 (mantissa (cadr l))
251 (exponent (caddr l))
252 (fpprec machine-mantissa-precision)
253 (*m 0))
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)))
266 (if (>= e 1025)
267 (merror (intl:gettext "float: floating point overflow converting ~:M") l)
268 (scale-float mantissa e))))
271 (defun decbcons (s)
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
279 (cond
280 ((bigfloatp x)) ; return x, possibly changed precision
281 ((numberp x) ;; favors decimal conversion for CL numbers
282 (decintofp x))
283 #+ignore
284 ((numberp x) ;; favors binary conversion for CL numbers
285 (bcons (intofp x)))
286 ((atom x)($binarybfloat x)) ; %pi, %phi
287 ((eq (caar x) 'rat)
288 (decrat2fp x))
289 ((and(eq (caar x) 'mexpt)
290 (decimalfpp (cadr x))
291 (integerp (caddr x))
292 (>= (caddr x) 0))
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)
305 (cond
306 ((decimalfpp 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
312 (decrat2fp x))
313 ((atom x)($binarybfloat x)) ; %pi, %phi
314 ((eq (caar x) 'rat)
315 (decrat2fp x))
316 ((and(eq (caar x) 'mexpt)
317 (decimalfpp (cadr x))
318 (integerp (caddr x))
319 (>= (caddr x) 0))
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
326 (let ((ans '(1 0))
327 (b (cdr ba)))
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 )
332 ((or (numberp x)
333 (member x '($%e $%pi $%gamma) :test #'eq))
334 (bcons (intofp x)))
335 ((or (atom x) (member 'array (cdar x) :test #'eq))
336 (if (eq x '$%phi)
337 ($binarybfloat '((mtimes simp)
338 ((rat simp) 1 2)
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))
345 (caddr x)
346 ;;(decfp2binfp(caddr x))
348 ((eq (caar x) 'mncexpt)
349 (list '(mncexpt) ($binarybfloat (cadr x)) (caddr x)))
350 ((eq (caar x) 'rat)
351 (ratbigfloat (cdr x)))
352 ((setq y (safe-get (caar x) 'floatprog))
353 (funcall y (mapcar #'$binarybfloat (cdr x)))
355 ;; removed stuff here
356 #+ignore
357 ((or (trigp (caar x)) (arcp (caar x)) (eq (caar x) '$entier))
358 (setq y ($binarybfloat (cadr x)))
359 (if ($bfloatp y)
360 (cond ((eq (caar x) '$entier) ($entier y))
361 ((arcp (caar x))
362 (setq y ($binarybfloat (logarc (caar x) y)))
363 (if (free y '$%i)
364 y (let ($ratprint) (fparcsimp ($rectform y)))))
365 ((member (caar x) '(%cot %sec %csc) :test #'eq)
366 (invertbigfloat
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...
400 (let ((program
401 `(lambda(f)(let ((a (car f)))
402 (,k (if (decimalfpp a) (list(decfp2binfp a))
403 f ))))))
404 (format t "~%redefining bigfloat ~s to also work for decimal bigfloat" j)
405 (setf (get j 'floatprog) (compile nil program))))))
407 (eval-when
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)
416 (let* ((a (car l))
417 (r (bigfloatp a)))
418 ;; (format t "~%decmabsbigfloat a=~s r=~s" a r)
419 (cond ((null r) (list '(mabs) a))
420 ((decimalfpp 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)))
428 ;;etc
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))
447 (r nil)
448 (fans nil))
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
456 (let ()
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)))))
462 ;; all are decimal
463 (let()
464 (setf fans (decbcons '(0 0)))
465 (map nil #'(lambda(z)
466 (setf r ($bfloat z))
467 (setq fans (decbcons (decfpplus (cdr r)(cdr fans)))))
468 h)))
469 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))
482 (let* ((n (cadr r))
483 (d (caddr r))
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)))))
488 ((integerp r)
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
497 (defun decintofp (l)
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))
512 (car b)))
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)))
528 ((> exp 0)
529 (list (+ (* (expt 10 exp) (car a))
530 (car b))
531 (cadr b)))
533 (t (list (+ (* (car b)(expt 10 (- exp)))
534 (car a))
535 (cadr a))))))
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
542 (r nil)
543 (fans nil))
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
551 (let ()
552 (setf fans (bcons(fpone)))
553 (map nil #'(lambda(z)
554 (setf r (bigfloatp z))
555 (setq fans (bcons (fptimes* (cdr r)(cdr fans)))))
557 ;; all are decimal
558 (let()
560 (setf fans (decbcons '(1 0)))
561 (map nil #'(lambda(z)
562 (setf r ($bfloat z))
563 (setq fans (decbcons (decfptimes (cdr r)(cdr fans)))))
564 h)))
565 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)))))
579 (if (> nn fixprec)
580 (fptimes* (decintofp (expt int (rem nn fixprec)))
581 (fpexpt bas (quotient nn fixprec)))
582 bas)))
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)
590 (prog (fans r nfans)
591 (setq fans (decbcons (fpone)) nfans 1)
592 (do ((l h (cdr l)))
593 ((null l))
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)
598 fans
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)
604 (cdr(decfp2binfp a))
605 (cdr a)))))
607 ;;; taken out of nparse.lisp.
609 #| there is something broken in GCL Maxima. 123L0 says "incorrect syntax"
610 This doesn't fix it.
611 (defun scan-number-exponent (data)
612 (push (ncons (if (or (char= (parse-tyipeek) #\+)
613 (char= (parse-tyipeek) #\-))
614 (parse-tyi)
615 #\+))
616 data)
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
620 ;;#\L #\l
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
625 #\L #\l
626 #+cmu #\W #+cmu #\w)
627 #'scan-number-rest))
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+)
636 (when
637 #+ignore
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+)))))
642 (cond
644 ((equal (nth 3 data) '(#\B))
645 ;; (format t "~% exponent B data=~s~%" data)
646 (let*
647 ((*read-base* 10.)
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 #\-)
666 (- exp)
667 exp)
668 frac-len)))
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.
679 (bigfloatp result)))
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 #\-)
687 (- exp)
688 exp)))))
689 ($binarybfloat (cl-rat-to-maxima ratio))))))
690 ;; decimal input
691 ((equal (nth 3 data) '(#\L))
692 ;; (format t "~% exponent L data=~s~%" data)
693 (let*
694 ((*read-base* 10.)
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))))
701 (let* ((bigmant
702 (+ frac-part (* int-part (expt 10 frac-len))))
703 (bigexp (- (if (char= exp-sign #\-)
704 (- exp)
705 exp) frac-len)) )
707 (decbcons (list bigmant bigexp)))))
708 (t (readlist (apply #'append data)))))
711 ;; from maxmin.lisp
713 (defmfun $rationalize (e)
715 (setq e (ratdisrep e))
716 (cond ((floatp 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)))))
721 #+ignore
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)))))
726 (($mapatom e) e)
727 (t (simplify (cons (list (mop e)) (mapcar #'$rationalize (margs e)))))))
729 ;; from trigi
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))
735 (y ($imagpart 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
741 ;; rectform version.
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)))
749 ($bfloat z)))))))))
752 rationalize(1.0b-1)-1/10 ; should be non-zero
753 rationalize(1.0L-1)-1/10 ; ; should be zero
756 (eval-when
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.
762 #+ignore
763 (defmfun $decfloor(f)
764 (if (decimalfpp f) (floor (* (cadr f)(expt 10 (caddr f))))
765 (mfuncall '$floor f)))
767 #+ignore
768 (defmfun $decceiling(f)
769 (if (decimalfpp f)(ceiling (* (cadr f)(expt 10 (caddr f))))
770 (mfuncall '$ceiling f)))
772 #+ignore
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)
805 ;; from numeric.lisp
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
813 (cond (im
814 (make-instance 'complex-bigfloat
815 :real (intofp re)
817 :imag (intofp im)))
818 ((cl:realp re)
819 (make-instance 'bigfloat :real (intofp re)))
820 ((cl:complexp 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??
851 remainder (6.1L0,6)
853 atan2(3.0l0,4) works