2 (:use
"COMMON-LISP" "SB-ALIEN" "SB-C-CALL")
8 ;; +mpfr-precision+ is a pseudo-constant
9 ;; Do not set via LET but use the two methods below!
13 ;; parameters and types
17 ;; arithmetic operations
19 #:mpfr-float-to-string
80 #:arithmetic-geometric-mean
85 ;; comparison functions and predicates
107 ;; miscellaneous functions
116 #:set-div-by-zero-flag
127 ;; random number generation
132 #:rounded-int-ceiling
135 #:rounded-int-truncate
182 (in-package :sb-mpfr
)
184 (defvar +mpfr-precision
+)
185 (defvar *mpfr-version
* nil
)
186 (defvar *mpfr-features
* nil
)
188 (defun try-load-shared-object (pathname)
190 (load-shared-object pathname
:dont-save t
)
195 (or (some #'try-load-shared-object
196 #-
(or win32 darwin
) '("libmpfr.so" "libmpfr.so.4")
197 #+darwin
'("libmpfr.dylib" "libmpfr.4.dylib")
198 #+win32
'("mpfr.dll"))
199 (warn "MPFR not loaded.")))
201 (defun load-mpfr (&key
(persistently t
))
202 (setf *mpfr-version
* nil
204 *features
* (set-difference *features
* '(:sb-mpfr
)))
206 (pushnew 'load-mpfr sb-ext
:*init-hooks
*)
207 ;(pushnew 'uninstall-mpfr-funs sb-ext:*save-hooks*)
209 (let ((success (%load-mpfr
)))
212 (alien-funcall (extern-alien "mpfr_get_version"
213 (function c-string
)))))
214 (cond ((null *mpfr-version
*))
215 ((string<= *mpfr-version
* "3.1")
216 (warn "SB-MPFR requires at least MPFR version 3.1")
219 (setf +mpfr-precision
+
220 (alien-funcall (extern-alien "mpfr_get_default_prec"
222 (pushnew :sb-mpfr
*mpfr-features
*)
223 (setf *features
* (union *features
* *mpfr-features
*))))
228 ;;; types and initialization
230 (define-alien-type nil
235 (mpfr_d (* unsigned-long
))))
237 (define-alien-type mpfr_rnd_enum
247 (declaim (inline mpfr_init2
259 mpfr_set_default_prec
262 (define-alien-routine mpfr_init2 void
263 (x (* (struct mpfrfloat
)))
266 (define-alien-routine mpfr_clear void
267 (x (* (struct mpfrfloat
))))
269 ;;; conversion functions
271 (define-alien-routine mpfr_set void
272 (x (* (struct mpfrfloat
)))
273 (op (* (struct mpfrfloat
)))
276 (define-alien-routine mpfr_set_ui void
277 (x (* (struct mpfrfloat
)))
281 (define-alien-routine mpfr_set_si void
282 (x (* (struct mpfrfloat
)))
286 (define-alien-routine mpfr_set_flt void
287 (x (* (struct mpfrfloat
)))
291 (define-alien-routine mpfr_set_d void
292 (x (* (struct mpfrfloat
)))
296 (define-alien-routine mpfr_set_z void
297 (x (* (struct mpfrfloat
)))
298 (op (* (struct sb-gmp
::gmpint
)))
301 (define-alien-routine mpfr_set_q void
302 (x (* (struct mpfrfloat
)))
303 (op (* (struct sb-gmp
::gmprat
)))
306 (define-alien-routine mpfr_set_nan void
307 (x (* (struct mpfrfloat
))))
309 (define-alien-routine mpfr_set_inf void
310 (x (* (struct mpfrfloat
)))
313 (define-alien-routine mpfr_set_zero void
314 (x (* (struct mpfrfloat
)))
317 (define-alien-routine mpfr_set_default_prec void
320 (define-alien-routine mpfr_get_str
(* char
)
325 (x (* (struct mpfrfloat
)))
328 ;;; conversion functions
330 (declaim (inline mpfr_get_flt
338 (define-alien-routine mpfr_get_flt float
339 (op (* (struct mpfrfloat
)))
342 (define-alien-routine mpfr_get_d double
343 (op (* (struct mpfrfloat
)))
346 (define-alien-routine mpfr_get_si long
347 (op (* (struct mpfrfloat
)))
350 (define-alien-routine mpfr_get_ui unsigned-long
351 (op (* (struct mpfrfloat
)))
354 (define-alien-routine mpfr_get_z int
355 (res (* (struct sb-gmp
::gmpint
)))
356 (op (* (struct mpfrfloat
)))
359 (define-alien-routine mpfr_free_str void
362 (define-alien-routine mpfr_set_str int
363 (x (* (struct mpfrfloat
)))
368 ;;; arithmetic functions
370 (declaim (inline mpfr_add
420 (define-alien-routine mpfr_add int
421 (r (* (struct mpfrfloat
)))
422 (op1 (* (struct mpfrfloat
)))
423 (op2 (* (struct mpfrfloat
)))
426 (define-alien-routine mpfr_add_ui int
427 (r (* (struct mpfrfloat
)))
428 (op1 (* (struct mpfrfloat
)))
432 (define-alien-routine mpfr_add_si int
433 (r (* (struct mpfrfloat
)))
434 (op1 (* (struct mpfrfloat
)))
438 (define-alien-routine mpfr_add_d int
439 (r (* (struct mpfrfloat
)))
440 (op1 (* (struct mpfrfloat
)))
444 (define-alien-routine mpfr_add_z int
445 (r (* (struct mpfrfloat
)))
446 (op1 (* (struct mpfrfloat
)))
447 (op2 (* (struct sb-gmp
::gmpint
)))
450 (define-alien-routine mpfr_add_q int
451 (r (* (struct mpfrfloat
)))
452 (op1 (* (struct mpfrfloat
)))
453 (op2 (* (struct sb-gmp
::gmprat
)))
456 (define-alien-routine mpfr_sub int
457 (r (* (struct mpfrfloat
)))
458 (op1 (* (struct mpfrfloat
)))
459 (op2 (* (struct mpfrfloat
)))
462 (define-alien-routine mpfr_ui_sub int
463 (r (* (struct mpfrfloat
)))
465 (op2 (* (struct mpfrfloat
)))
468 (define-alien-routine mpfr_sub_ui int
469 (r (* (struct mpfrfloat
)))
470 (op1 (* (struct mpfrfloat
)))
474 (define-alien-routine mpfr_si_sub int
475 (r (* (struct mpfrfloat
)))
477 (op2 (* (struct mpfrfloat
)))
480 (define-alien-routine mpfr_sub_si int
481 (r (* (struct mpfrfloat
)))
482 (op1 (* (struct mpfrfloat
)))
486 (define-alien-routine mpfr_d_sub int
487 (r (* (struct mpfrfloat
)))
489 (op2 (* (struct mpfrfloat
)))
492 (define-alien-routine mpfr_sub_d int
493 (r (* (struct mpfrfloat
)))
494 (op1 (* (struct mpfrfloat
)))
498 (define-alien-routine mpfr_z_sub int
499 (r (* (struct mpfrfloat
)))
500 (op1 (* (struct sb-gmp
::gmpint
)))
501 (op2 (* (struct mpfrfloat
)))
504 (define-alien-routine mpfr_sub_z int
505 (r (* (struct mpfrfloat
)))
506 (op1 (* (struct mpfrfloat
)))
507 (op2 (* (struct sb-gmp
::gmpint
)))
510 (define-alien-routine mpfr_sub_q int
511 (r (* (struct mpfrfloat
)))
512 (op1 (* (struct mpfrfloat
)))
513 (op2 (* (struct sb-gmp
::gmprat
)))
516 (define-alien-routine mpfr_mul int
517 (r (* (struct mpfrfloat
)))
518 (op1 (* (struct mpfrfloat
)))
519 (op2 (* (struct mpfrfloat
)))
522 (define-alien-routine mpfr_mul_ui int
523 (r (* (struct mpfrfloat
)))
524 (op1 (* (struct mpfrfloat
)))
528 (define-alien-routine mpfr_mul_si int
529 (r (* (struct mpfrfloat
)))
530 (op1 (* (struct mpfrfloat
)))
534 (define-alien-routine mpfr_mul_d int
535 (r (* (struct mpfrfloat
)))
536 (op1 (* (struct mpfrfloat
)))
540 (define-alien-routine mpfr_mul_z int
541 (r (* (struct mpfrfloat
)))
542 (op1 (* (struct mpfrfloat
)))
543 (op2 (* (struct sb-gmp
::gmpint
)))
546 (define-alien-routine mpfr_mul_q int
547 (r (* (struct mpfrfloat
)))
548 (op1 (* (struct mpfrfloat
)))
549 (op2 (* (struct sb-gmp
::gmprat
)))
552 (define-alien-routine mpfr_sqr int
553 (r (* (struct mpfrfloat
)))
554 (op (* (struct mpfrfloat
)))
557 (define-alien-routine mpfr_div int
558 (r (* (struct mpfrfloat
)))
559 (op1 (* (struct mpfrfloat
)))
560 (op2 (* (struct mpfrfloat
)))
563 (define-alien-routine mpfr_ui_div int
564 (r (* (struct mpfrfloat
)))
566 (op2 (* (struct mpfrfloat
)))
569 (define-alien-routine mpfr_div_ui int
570 (r (* (struct mpfrfloat
)))
571 (op1 (* (struct mpfrfloat
)))
575 (define-alien-routine mpfr_si_div int
576 (r (* (struct mpfrfloat
)))
578 (op2 (* (struct mpfrfloat
)))
581 (define-alien-routine mpfr_div_si int
582 (r (* (struct mpfrfloat
)))
583 (op1 (* (struct mpfrfloat
)))
587 (define-alien-routine mpfr_d_div int
588 (r (* (struct mpfrfloat
)))
590 (op2 (* (struct mpfrfloat
)))
593 (define-alien-routine mpfr_div_d int
594 (r (* (struct mpfrfloat
)))
595 (op1 (* (struct mpfrfloat
)))
599 (define-alien-routine mpfr_div_z int
600 (r (* (struct mpfrfloat
)))
601 (op1 (* (struct mpfrfloat
)))
602 (op2 (* (struct sb-gmp
::gmpint
)))
605 (define-alien-routine mpfr_div_q int
606 (r (* (struct mpfrfloat
)))
607 (op1 (* (struct mpfrfloat
)))
608 (op2 (* (struct sb-gmp
::gmprat
)))
611 (define-alien-routine mpfr_sqrt int
612 (r (* (struct mpfrfloat
)))
613 (op (* (struct mpfrfloat
)))
616 (define-alien-routine mpfr_sqrt_ui int
617 (r (* (struct mpfrfloat
)))
621 (define-alien-routine mpfr_rec_sqrt int
622 (r (* (struct mpfrfloat
)))
623 (op (* (struct mpfrfloat
)))
626 (define-alien-routine mpfr_cbrt int
627 (r (* (struct mpfrfloat
)))
628 (op (* (struct mpfrfloat
)))
631 (define-alien-routine mpfr_root int
632 (r (* (struct mpfrfloat
)))
633 (op (* (struct mpfrfloat
)))
637 (define-alien-routine mpfr_pow int
638 (r (* (struct mpfrfloat
)))
639 (op1 (* (struct mpfrfloat
)))
640 (op2 (* (struct mpfrfloat
)))
643 (define-alien-routine mpfr_pow_ui int
644 (r (* (struct mpfrfloat
)))
645 (op1 (* (struct mpfrfloat
)))
649 (define-alien-routine mpfr_pow_si int
650 (r (* (struct mpfrfloat
)))
651 (op1 (* (struct mpfrfloat
)))
655 (define-alien-routine mpfr_pow_z int
656 (r (* (struct mpfrfloat
)))
657 (op1 (* (struct mpfrfloat
)))
658 (op2 (* (struct sb-gmp
::gmpint
)))
661 (define-alien-routine mpfr_ui_pow int
662 (r (* (struct mpfrfloat
)))
664 (op2 (* (struct mpfrfloat
)))
667 (define-alien-routine mpfr_neg int
668 (r (* (struct mpfrfloat
)))
669 (op (* (struct mpfrfloat
)))
672 (define-alien-routine mpfr_abs int
673 (r (* (struct mpfrfloat
)))
674 (op (* (struct mpfrfloat
)))
677 (define-alien-routine mpfr_dim int
678 (r (* (struct mpfrfloat
)))
679 (op1 (* (struct mpfrfloat
)))
680 (op2 (* (struct mpfrfloat
)))
683 (define-alien-routine mpfr_mul_2ui int
684 (r (* (struct mpfrfloat
)))
685 (op1 (* (struct mpfrfloat
)))
689 (define-alien-routine mpfr_mul_2si int
690 (r (* (struct mpfrfloat
)))
691 (op1 (* (struct mpfrfloat
)))
695 (define-alien-routine mpfr_div_2ui int
696 (r (* (struct mpfrfloat
)))
697 (op1 (* (struct mpfrfloat
)))
701 (define-alien-routine mpfr_div_2si int
702 (r (* (struct mpfrfloat
)))
703 (op1 (* (struct mpfrfloat
)))
707 ;;; special functions
709 (defmacro define-onearg-mpfr-int
(funs)
710 (loop for i in funs collect
`(define-alien-routine ,i int
711 (r (* (struct mpfrfloat
)))
712 (op (* (struct mpfrfloat
)))
715 finally
(return `(progn
716 (declaim (inline ,@funs
))
719 (define-onearg-mpfr-int
760 (defmacro define-twoarg-mpfr-int
(funs)
761 (loop for i in funs collect
`(define-alien-routine ,i int
762 (r (* (struct mpfrfloat
)))
763 (op1 (* (struct mpfrfloat
)))
764 (op2 (* (struct mpfrfloat
)))
767 finally
(return `(progn
768 (declaim (inline ,@funs
))
771 (define-twoarg-mpfr-int
778 (declaim (inline mpfr_fac_ui
785 (define-alien-routine mpfr_fac_ui int
786 (r (* (struct mpfrfloat
)))
790 (define-alien-routine mpfr_zeta_ui int
791 (r (* (struct mpfrfloat
)))
795 (define-alien-routine mpfr_jn int
796 (r (* (struct mpfrfloat
)))
798 (op (* (struct mpfrfloat
)))
801 (define-alien-routine mpfr_yn int
802 (r (* (struct mpfrfloat
)))
804 (op (* (struct mpfrfloat
)))
807 (define-alien-routine mpfr_fma int
808 (r (* (struct mpfrfloat
)))
809 (op1 (* (struct mpfrfloat
)))
810 (op2 (* (struct mpfrfloat
)))
811 (op3 (* (struct mpfrfloat
)))
814 (define-alien-routine mpfr_fms int
815 (r (* (struct mpfrfloat
)))
816 (op1 (* (struct mpfrfloat
)))
817 (op2 (* (struct mpfrfloat
)))
818 (op3 (* (struct mpfrfloat
)))
822 ;;; constant initialization
824 (defmacro define-const-mpfr-int
(funs)
825 (loop for i in funs collect
`(define-alien-routine ,i int
826 (r (* (struct mpfrfloat
)))
829 finally
(return `(progn
830 (declaim (inline ,@funs
))
833 (define-const-mpfr-int
839 (declaim (inline mpfr_sum
))
840 (define-alien-routine mpfr_sum int
841 (r (* (struct mpfrfloat
)))
842 (tab (* (* (struct mpfrfloat
))))
847 ;;; comparison functions
849 (declaim (inline mpfr_cmp
859 (define-alien-routine mpfr_cmp int
860 (op1 (* (struct mpfrfloat
)))
861 (op2 (* (struct mpfrfloat
))))
863 (define-alien-routine mpfr_cmp_ui int
864 (op1 (* (struct mpfrfloat
)))
867 (define-alien-routine mpfr_cmp_si int
868 (op1 (* (struct mpfrfloat
)))
871 (define-alien-routine mpfr_cmp_d int
872 (op1 (* (struct mpfrfloat
)))
875 (define-alien-routine mpfr_cmp_z int
876 (op1 (* (struct mpfrfloat
)))
877 (op2 (* (struct sb-gmp
::gmpint
))))
879 (define-alien-routine mpfr_cmp_q int
880 (op1 (* (struct mpfrfloat
)))
881 (op2 (* (struct sb-gmp
::gmprat
))))
883 (define-alien-routine mpfr_cmp_ui_2exp int
884 (op1 (* (struct mpfrfloat
)))
888 (define-alien-routine mpfr_cmp_si_2exp int
889 (op1 (* (struct mpfrfloat
)))
893 (define-alien-routine mpfr_cmpabs int
894 (op1 (* (struct mpfrfloat
)))
895 (op2 (* (struct mpfrfloat
))))
898 (defmacro define-onearg-mpfr-bool
(funs)
899 (loop for i in funs collect
`(define-alien-routine ,i boolean
900 (op (* (struct mpfrfloat
))))
902 finally
(return `(progn
903 (declaim (inline ,@funs
))
906 (define-onearg-mpfr-bool
914 (declaim (inline mpfr_sgn
))
915 (define-alien-routine mpfr_sgn int
916 (op (* (struct mpfrfloat
))))
918 (defmacro define-twoarg-mpfr-bool
(funs)
919 (loop for i in funs collect
`(define-alien-routine ,i boolean
920 (op1 (* (struct mpfrfloat
)))
921 (op2 (* (struct mpfrfloat
))))
923 finally
(return `(progn
924 (declaim (inline ,@funs
))
927 (define-twoarg-mpfr-bool
937 ;;; miscellaneous functions
939 (defmacro define-mpfr-void
(funs)
940 (loop for i in funs collect
`(define-alien-routine ,i void
)
942 finally
(return `(progn
943 (declaim (inline ,@funs
))
947 (mpfr_clear_underflow
952 mpfr_clear_erangeflag
961 (defmacro define-mpfr-bool
(funs)
962 (loop for i in funs collect
`(define-alien-routine ,i boolean
)
964 finally
(return `(progn
965 (declaim (inline ,@funs
))
977 (declaim (inline mpfr_urandomb
980 (define-alien-routine mpfr_urandomb int
981 (op (* (struct mpfrfloat
)))
982 (s (* (struct sb-gmp
::gmprandstate
))))
984 (define-alien-routine mpfr_urandom int
985 (op (* (struct mpfrfloat
)))
986 (s (* (struct sb-gmp
::gmprandstate
)))
990 ;;; integer and remainder related functions / rounding
992 (define-onearg-mpfr-int
1000 (declaim (inline mpfr_ceil
1009 (define-alien-routine mpfr_ceil int
1010 (r (* (struct mpfrfloat
)))
1011 (op (* (struct mpfrfloat
))))
1013 (define-alien-routine mpfr_floor int
1014 (r (* (struct mpfrfloat
)))
1015 (op (* (struct mpfrfloat
))))
1017 (define-alien-routine mpfr_round int
1018 (r (* (struct mpfrfloat
)))
1019 (op (* (struct mpfrfloat
))))
1021 (define-alien-routine mpfr_trunc int
1022 (r (* (struct mpfrfloat
)))
1023 (op (* (struct mpfrfloat
))))
1025 (define-alien-routine mpfr_modf int
1026 (ir (* (struct mpfrfloat
)))
1027 (fr (* (struct mpfrfloat
)))
1028 (op (* (struct mpfrfloat
)))
1029 (rnd mpfr_rnd_enum
))
1031 (define-alien-routine mpfr_fmod int
1032 (r (* (struct mpfrfloat
)))
1033 (x (* (struct mpfrfloat
)))
1034 (y (* (struct mpfrfloat
)))
1035 (rnd mpfr_rnd_enum
))
1037 (define-alien-routine mpfr_remainder int
1038 (r (* (struct mpfrfloat
)))
1039 (x (* (struct mpfrfloat
)))
1040 (y (* (struct mpfrfloat
)))
1041 (rnd mpfr_rnd_enum
))
1043 (define-alien-routine mpfr_remquo int
1044 (r (* (struct mpfrfloat
)))
1046 (x (* (struct mpfrfloat
)))
1047 (y (* (struct mpfrfloat
)))
1048 (rnd mpfr_rnd_enum
))
1053 (defparameter *mpfr-rnd
* :mpfr_rndn
)
1054 (defparameter *mpfr-base
* 10)
1056 (declaim (inline mpfr-float-ref
1059 (defstruct (mpfr-float (:constructor %make-mpfr-float
))
1060 (ref (make-alien (struct mpfrfloat
))
1061 :type
(alien (* (struct mpfrfloat
))) :read-only t
))
1063 (defun make-mpfr-float (&optional
(precision +mpfr-precision
+))
1064 (declare (optimize (speed 3) (space 3)))
1065 (let* ((float (%make-mpfr-float
))
1066 (ref (mpfr-float-ref float
)))
1067 (mpfr_init2 ref precision
)
1068 (sb-ext:finalize float
(lambda ()
1069 (declare (optimize (speed 3) (space 3) (safety 0)))
1074 (defmacro with-precision
(value &body body
)
1075 `(let* ((old +mpfr-precision
+)
1076 (+mpfr-precision
+ ,value
))
1079 (mpfr_set_default_prec ,value
)
1081 (mpfr_set_default_prec old
))))
1083 (defun set-precision (value)
1084 (check-type value
(unsigned-byte #.sb-vm
:n-word-bits
))
1085 (mpfr_set_default_prec value
)
1086 (setf +mpfr-precision
+ value
))
1088 ;;; printing and reader syntax
1090 (defmethod print-object ((obj mpfr-float
) stream
)
1091 (multiple-value-bind (str exp sign
)
1092 (mpfr-float-to-string obj
)
1093 (declare (type (integer -
1 1) sign
))
1094 (if *print-readably
*
1096 (format stream
"#M~s" str
)
1098 (0 (format stream
"#M\"0\""))
1099 (1 (format stream
"#M\"~a@~s\"" str
1100 (- exp
(length str
))))
1101 (-1 (format stream
"#M\"~a@~s\"" str
1102 (- (1+ exp
) (length str
))))))
1104 (format stream
"~a" str
)
1106 (0 (format stream
"0"))
1107 (1 (format stream
".~ae+~s" str exp
))
1108 (-1 (format stream
"-.~ae+~s" (subseq str
1) exp
)))))))
1110 (defun mpfr-float-to-string (x &optional
(rnd *mpfr-rnd
*))
1111 (let ((xr (mpfr-float-ref x
)))
1112 (with-alien ((exp long
)
1115 (setf str
(mpfr_get_str NIL
(addr exp
) *print-base
* 0 xr rnd
))
1116 (multiple-value-prog1
1117 (values (cast str c-string
) exp
(mpfr_cmp_ui xr
0))
1118 (mpfr_free_str str
)))))
1120 (defun mpfr-reader (stream subchar arg
)
1121 (declare (ignore subchar arg
))
1122 (let ((mpfr (make-mpfr-float)))
1123 (mpfr_set_str (mpfr-float-ref mpfr
)
1124 (read stream t nil t
)
1125 *mpfr-base
* *mpfr-rnd
*)
1128 (defun enable-mpfr-syntax (readtable)
1129 (set-dispatch-macro-character #\
# #\M
#'mpfr-reader readtable
))
1130 (enable-mpfr-syntax *readtable
*)
1133 ;;; arithmetic functions
1135 (defun add (x y
&optional
(round *mpfr-rnd
*))
1136 (if (typep x
'mpfr-float
)
1137 (let* ((res (make-mpfr-float))
1138 (r (mpfr-float-ref res
))
1139 (xr (mpfr-float-ref x
))
1142 (mpfr_add r xr
(mpfr-float-ref y
) round
))
1143 ((unsigned-byte #.sb-vm
:n-word-bits
)
1144 (mpfr_add_ui r xr y round
))
1145 ((signed-byte #.sb-vm
:n-word-bits
)
1146 (mpfr_add_si r xr y round
))
1148 (mpfr_add_d r xr y round
))
1150 (sb-gmp::with-mpz-vars
((y gy
))
1151 (mpfr_add_z r xr
(addr gy
) round
)))
1153 (sb-gmp::with-mpq-var
(y qy
)
1154 (mpfr_add_q r xr
(addr qy
) round
))))))
1160 (defun sub (x y
&optional
(round *mpfr-rnd
*))
1161 (let* ((res (make-mpfr-float))
1162 (r (mpfr-float-ref res
))
1165 (let ((xr (mpfr-float-ref x
)))
1168 (mpfr_sub r xr
(mpfr-float-ref y
) round
))
1169 ((unsigned-byte #.sb-vm
:n-word-bits
)
1170 (mpfr_sub_ui r xr y round
))
1171 ((signed-byte #.sb-vm
:n-word-bits
)
1172 (mpfr_sub_si r xr y round
))
1174 (mpfr_sub_d r xr y round
))
1176 (sb-gmp::with-mpz-vars
((y gy
))
1177 (mpfr_sub_z r xr
(addr gy
) round
)))
1179 (sb-gmp::with-mpq-var
(y qy
)
1180 (mpfr_sub_q r xr
(addr qy
) round
))))))
1181 ((unsigned-byte #.sb-vm
:n-word-bits
)
1184 (mpfr_ui_sub r x
(mpfr-float-ref y
) round
))))
1185 ((signed-byte #.sb-vm
:n-word-bits
)
1188 (mpfr_si_sub r x
(mpfr-float-ref y
) round
))))
1192 (mpfr_d_sub r x
(mpfr-float-ref y
) round
))))
1196 (sb-gmp::with-mpz-vars
((x gx
))
1197 (mpfr_z_sub r
(addr gx
) (mpfr-float-ref y
) round
))))))))
1200 (defun mul (x y
&optional
(round *mpfr-rnd
*))
1201 (if (typep x
'mpfr-float
)
1202 (let* ((res (make-mpfr-float))
1203 (r (mpfr-float-ref res
))
1204 (xr (mpfr-float-ref x
))
1207 (mpfr_mul r xr
(mpfr-float-ref y
) round
))
1208 ((unsigned-byte #.sb-vm
:n-word-bits
)
1209 (mpfr_mul_ui r xr y round
))
1210 ((signed-byte #.sb-vm
:n-word-bits
)
1211 (mpfr_mul_si r xr y round
))
1213 (mpfr_mul_d r xr y round
))
1215 (sb-gmp::with-mpz-vars
((y gy
))
1216 (mpfr_mul_z r xr
(addr gy
) round
)))
1218 (sb-gmp::with-mpq-var
(y qy
)
1219 (mpfr_mul_q r xr
(addr qy
) round
))))))
1225 (defun sqare (x &optional
(round *mpfr-rnd
*))
1226 (let ((r (make-mpfr-float)))
1227 (values r
(mpfr_sqr (mpfr-float-ref r
) (mpfr-float-ref x
) round
))))
1229 (defun div (x y
&optional
(round *mpfr-rnd
*))
1230 (let* ((res (make-mpfr-float))
1231 (r (mpfr-float-ref res
))
1234 (let ((xr (mpfr-float-ref x
)))
1237 (mpfr_div r xr
(mpfr-float-ref y
) round
))
1238 ((unsigned-byte #.sb-vm
:n-word-bits
)
1239 (mpfr_div_ui r xr y round
))
1240 ((signed-byte #.sb-vm
:n-word-bits
)
1241 (mpfr_div_si r xr y round
))
1243 (mpfr_div_d r xr y round
))
1245 (sb-gmp::with-mpz-vars
((y gy
))
1246 (mpfr_div_z r xr
(addr gy
) round
)))
1248 (sb-gmp::with-mpq-var
(y qy
)
1249 (mpfr_div_q r xr
(addr qy
) round
))))))
1250 ((unsigned-byte #.sb-vm
:n-word-bits
)
1253 (mpfr_ui_div r x
(mpfr-float-ref y
) round
))))
1254 ((signed-byte #.sb-vm
:n-word-bits
)
1257 (mpfr_si_div r x
(mpfr-float-ref y
) round
))))
1261 (mpfr_d_div r x
(mpfr-float-ref y
) round
)))))))
1264 (defun sqrt (x &optional
(round *mpfr-rnd
*))
1265 (let* ((res (make-mpfr-float))
1266 (r (mpfr-float-ref res
))
1268 ((unsigned-byte #.sb-vm
:n-word-bits
)
1269 (mpfr_sqrt_ui r x round
))
1271 (mpfr_sqrt r
(mpfr-float-ref x
) round
)))))
1274 (defun reciprocal-sqrt (x &optional
(round *mpfr-rnd
*))
1275 (let* ((res (make-mpfr-float))
1276 (r (mpfr-float-ref res
))
1277 (i (mpfr_rec_sqrt r
(mpfr-float-ref x
) round
)))
1280 (defun cubic-root (x &optional
(round *mpfr-rnd
*))
1281 (let* ((res (make-mpfr-float))
1282 (r (mpfr-float-ref res
))
1283 (i (mpfr_cbrt r
(mpfr-float-ref x
) round
)))
1286 (defun k-root (x k
&optional
(round *mpfr-rnd
*))
1287 (check-type k
(unsigned-byte #.sb-vm
:n-word-bits
))
1288 (let* ((res (make-mpfr-float))
1289 (r (mpfr-float-ref res
))
1290 (i (mpfr_root r
(mpfr-float-ref x
) k round
)))
1293 (defun power (x y
&optional
(round *mpfr-rnd
*))
1294 (let* ((res (make-mpfr-float))
1295 (r (mpfr-float-ref res
))
1298 (let ((xr (mpfr-float-ref x
)))
1301 (mpfr_pow r xr
(mpfr-float-ref y
) round
))
1302 ((unsigned-byte #.sb-vm
:n-word-bits
)
1303 (mpfr_pow_ui r xr y round
))
1304 ((signed-byte #.sb-vm
:n-word-bits
)
1305 (mpfr_pow_si r xr y round
))
1307 (sb-gmp::with-mpz-vars
((y gy
))
1308 (mpfr_pow_z r xr
(addr gy
) round
))))))
1309 ((unsigned-byte #.sb-vm
:n-word-bits
)
1312 (mpfr_ui_pow r x
(mpfr-float-ref y
) round
)))))))
1315 (defun negate (x &optional
(round *mpfr-rnd
*))
1316 (let* ((res (make-mpfr-float))
1317 (r (mpfr-float-ref res
))
1318 (i (mpfr_neg r
(mpfr-float-ref x
) round
)))
1321 (defun abs (x &optional
(round *mpfr-rnd
*))
1322 (let* ((res (make-mpfr-float))
1323 (r (mpfr-float-ref res
))
1324 (i (mpfr_abs r
(mpfr-float-ref x
) round
)))
1327 (defun dim (x y
&optional
(round *mpfr-rnd
*))
1328 (let* ((res (make-mpfr-float))
1329 (r (mpfr-float-ref res
))
1330 (i (mpfr_dim r
(mpfr-float-ref x
) (mpfr-float-ref y
) round
)))
1333 (defun mul-2-raised (x y
&optional
(round *mpfr-rnd
*))
1335 (let* ((res (make-mpfr-float))
1336 (r (mpfr-float-ref res
))
1338 ((unsigned-byte #.sb-vm
:n-word-bits
)
1339 (mpfr_mul_2ui r
(mpfr-float-ref x
) y round
))
1340 ((signed-byte #.sb-vm
:n-word-bits
)
1341 (mpfr_mul_2si r
(mpfr-float-ref x
) y round
)))))
1344 (defun div-2-raised (x y
&optional
(round *mpfr-rnd
*))
1346 (let* ((res (make-mpfr-float))
1347 (r (mpfr-float-ref res
))
1349 ((unsigned-byte #.sb-vm
:n-word-bits
)
1350 (mpfr_div_2ui r
(mpfr-float-ref x
) y round
))
1351 ((signed-byte #.sb-vm
:n-word-bits
)
1352 (mpfr_div_2si r
(mpfr-float-ref x
) y round
)))))
1355 ;;; special functions
1357 (defmacro define-onearg-mpfr-funs
(funs)
1358 (loop for
(clfun mfun
) in funs
1359 collect
`(defun ,clfun
(x &optional
(round *mpfr-rnd
*))
1360 (let* ((result (make-mpfr-float))
1361 (i (,mfun
(mpfr-float-ref result
)
1366 finally
(return `(progn
1369 (define-onearg-mpfr-funs
1398 (lngamma mpfr_lngamma
)
1399 (digamma mpfr_digamma
)
1408 (defun atan (y &optional x
(round *mpfr-rnd
*))
1410 (let* ((result (make-mpfr-float))
1411 (i (mpfr_atan2 (mpfr-float-ref result
)
1416 (let* ((result (make-mpfr-float))
1417 (i (mpfr_atan (mpfr-float-ref result
)
1420 (values result i
))))
1422 (defun sin-cos (x &optional
(round *mpfr-rnd
*))
1423 (let* ((sin (make-mpfr-float))
1424 (cos (make-mpfr-float))
1425 (i (mpfr_sin_cos (mpfr-float-ref sin
)
1426 (mpfr-float-ref cos
)
1429 (values sin cos i
)))
1431 (defun sinh-cosh (x &optional
(round *mpfr-rnd
*))
1432 (let* ((sin (make-mpfr-float))
1433 (cos (make-mpfr-float))
1434 (i (mpfr_sinh_cosh (mpfr-float-ref sin
)
1435 (mpfr-float-ref cos
)
1438 (values sin cos i
)))
1440 (defun arithmetic-geometric-mean (u v
&optional
(round *mpfr-rnd
*))
1441 (let* ((result (make-mpfr-float))
1442 (i (mpfr_agm (mpfr-float-ref result
)
1448 (defun hypot (x y
&optional
(round *mpfr-rnd
*))
1449 (let* ((result (make-mpfr-float))
1450 (i (mpfr_hypot (mpfr-float-ref result
)
1456 (defun fac (x &optional
(round *mpfr-rnd
*))
1457 (let* ((result (make-mpfr-float))
1458 (i (mpfr_fac_ui (mpfr-float-ref result
)
1463 (defun zeta (x &optional
(round *mpfr-rnd
*))
1464 (let* ((result (make-mpfr-float))
1467 (mpfr_zeta (mpfr-float-ref result
)
1470 ((unsigned-byte #.sb-vm
:n-word-bits
)
1471 (mpfr_zeta_ui (mpfr-float-ref result
)
1476 (defun jn (n x
&optional
(round *mpfr-rnd
*))
1477 (check-type n
(unsigned-byte #.sb-vm
:n-word-bits
))
1478 (let* ((result (make-mpfr-float))
1479 (i (mpfr_jn (mpfr-float-ref result
)
1485 (defun yn (n x
&optional
(round *mpfr-rnd
*))
1486 (check-type n
(unsigned-byte #.sb-vm
:n-word-bits
))
1487 (let* ((result (make-mpfr-float))
1488 (i (mpfr_yn (mpfr-float-ref result
)
1494 (defun fma (x y z
&optional
(round *mpfr-rnd
*))
1495 "fma X Y Z = (X * Y) + Z"
1496 (let* ((result (make-mpfr-float))
1497 (i (mpfr_fma (mpfr-float-ref result
)
1504 (defun fms (x y z
&optional
(round *mpfr-rnd
*))
1505 "fma X Y Z = (X * Y) - Z"
1506 (let* ((result (make-mpfr-float))
1507 (i (mpfr_fms (mpfr-float-ref result
)
1514 (defun sum (seq &optional
(round *mpfr-rnd
*))
1515 (let ((length (length seq
))
1517 (declare (type (integer -
1 #.most-positive-fixnum
) idx
))
1518 (let ((result (make-mpfr-float))
1519 (ar (make-alien (* (struct mpfrfloat
)) length
)))
1522 (map nil
(lambda (x)
1523 (setf (deref ar
(incf idx
))
1524 (mpfr-float-ref x
)))
1526 (let ((i (mpfr_sum (mpfr-float-ref result
)
1536 (defmacro define-const-mpfr-funs
(funs)
1537 (loop for
(fname mname
) in funs
1538 collect
`(defun ,fname
(&optional
(round *mpfr-rnd
*))
1539 (let* ((result (make-mpfr-float))
1540 (i (,mname
(mpfr-float-ref result
)
1544 finally
(return `(progn
1547 (define-const-mpfr-funs
1548 ((const-log2 mpfr_const_log2
)
1549 (const-pi mpfr_const_pi
)
1550 (const-euler mpfr_const_euler
)
1551 (const-catalan mpfr_const_catalan
)))
1553 ;;; comparison functions and predicates
1555 (defmacro define-onearg-mpfr-predicates
(funs)
1556 (loop for
(fname mname
) in funs
1557 collect
`(defun ,fname
(x)
1558 (,mname
(mpfr-float-ref x
)))
1560 finally
(return `(progn
1563 (define-onearg-mpfr-predicates
1565 (infinityp mpfr_inf_p
)
1566 (numberp mpfr_number_p
)
1568 (integerp mpfr_integer_p
)
1569 (regularp mpfr_regular_p
)))
1571 (defmacro define-twoarg-mpfr-predicates
(funs)
1572 (loop for
(fname mname
) in funs
1573 collect
`(defun ,fname
(x y
)
1574 (,mname
(mpfr-float-ref x
)
1575 (mpfr-float-ref y
)))
1577 finally
(return `(progn
1580 (define-twoarg-mpfr-predicates
1581 ((compare-abs mpfr_cmpabs
)
1583 (>= mpfr_greaterequal_p
)
1585 (<= mpfr_lessequal_p
)
1587 (/= mpfr_lessgreater_p
)
1588 (unorderedp mpfr_unordered_p
)))
1590 (defun compare (x y
)
1591 (if (typep x
'mpfr-float
)
1594 (mpfr_cmp (mpfr-float-ref x
)
1595 (mpfr-float-ref y
)))
1596 ((unsigned-byte #.sb-vm
:n-word-bits
)
1597 (mpfr_cmp_ui (mpfr-float-ref x
) y
))
1598 ((signed-byte #.sb-vm
:n-word-bits
)
1599 (mpfr_cmp_si (mpfr-float-ref x
) y
))
1601 (mpfr_cmp_d (mpfr-float-ref x
) y
))
1603 (sb-gmp::with-mpz-vars
((y gy
))
1604 (mpfr_cmp_z (mpfr-float-ref x
) (addr gy
))))
1606 (sb-gmp::with-mpq-var
(y qy
)
1607 (mpfr_cmp_q (mpfr-float-ref x
) (addr qy
)))))
1612 (defun compare-2exp (x y exp
)
1613 (if (typep x
'mpfr-float
)
1615 ((unsigned-byte #.sb-vm
:n-word-bits
)
1616 (mpfr_cmp_ui_2exp (mpfr-float-ref x
) y exp
))
1617 ((signed-byte #.sb-vm
:n-word-bits
)
1618 (mpfr_cmp_si_2exp (mpfr-float-ref x
) y exp
)))
1621 (compare-2exp y x exp
)))))
1624 ;;; miscellaneous functions
1626 (defmacro define-mpfr-flag-funs
(funs)
1627 (loop for
(pname mname
) in funs
1628 collect
`(defun ,pname
()
1629 (declare (optimize (speed 3) (space 3)))
1632 collect pname into names
1633 finally
(return `(progn
1634 (declaim (inline ,@names
))
1637 (define-mpfr-flag-funs
1638 ((clear-underflow mpfr_clear_underflow
)
1639 (clear-overflow mpfr_clear_overflow
)
1640 (clear-div-by-zero mpfr_clear_divby0
)
1641 (clear-nan-flag mpfr_clear_nanflag
)
1642 (clear-inex-flag mpfr_clear_inexflag
)
1643 (clear-erange-flag mpfr_clear_erangeflag
)
1644 (set-underflow-flag mpfr_set_underflow
)
1645 (set-overflow-flag mpfr_set_overflow
)
1646 (set-div-by-zero-flag mpfr_set_divby0
)
1647 (set-nan-flag mpfr_set_nanflag
)
1648 (set-inex-flag mpfr_set_inexflag
)
1649 (set-erange-flag mpfr_set_erangeflag
)
1650 (clear-flags mpfr_clear_flags
)))
1653 (defmacro define-mpfr-flag-predicates
(funs)
1654 (loop for
(pname mname
) in funs
1655 collect
`(defun ,pname
()
1656 (declare (optimize (speed 3) (space 3)))
1659 collect pname into names
1660 finally
(return `(progn
1661 (declaim (inline ,@names
))
1664 (define-mpfr-flag-predicates
1665 ((underflowp mpfr_underflow_p
)
1666 (overflowp mpfr_overflow_p
)
1667 (div-by-zero-p mpfr_divby0_p
)
1668 (nanflag-p mpfr_nanflag_p
)
1669 (inexflag-p mpfr_inexflag_p
)
1670 (erangeflag-p mpfr_erangeflag_p
)))
1673 ;;; random number generation
1675 (defun urandomb (state)
1676 (check-type state sb-gmp
::gmp-rstate
)
1677 (let* ((ref (sb-gmp::gmp-rstate-ref state
))
1678 (result (make-mpfr-float))
1679 (i (mpfr_urandomb (mpfr-float-ref result
)
1683 (defun urandom (state &optional
(round *mpfr-rnd
*))
1684 (check-type state sb-gmp
::gmp-rstate
)
1685 (let* ((ref (sb-gmp::gmp-rstate-ref state
))
1686 (result (make-mpfr-float))
1687 (i (mpfr_urandom (mpfr-float-ref result
)
1693 ;;; integer and remainder related functions / rounding
1695 (define-onearg-mpfr-funs
1696 ((rounded-int mpfr_rint
)
1697 (rounded-int-ceiling mpfr_rint_ceil
)
1698 (rounded-int-floor mpfr_rint_floor
)
1699 (rounded-int-round mpfr_rint_round
)
1700 (rounded-int-truncate mpfr_rint_trunc
)
1701 (fractional mpfr_frac
)))
1703 (defmacro define-onearg-no-rnd-mpfr-funs
(funs)
1704 (loop for
(clfun mfun
) in funs
1705 collect
`(defun ,clfun
(x)
1706 (let* ((result (make-mpfr-float))
1707 (i (,mfun
(mpfr-float-ref result
)
1708 (mpfr-float-ref x
))))
1711 finally
(return `(progn
1714 (define-onearg-no-rnd-mpfr-funs
1718 (truncate mpfr_trunc
)))
1720 (defun modf (x &optional
(round *mpfr-rnd
*))
1721 (let* ((integral (make-mpfr-float))
1722 (fractional (make-mpfr-float))
1723 (i (mpfr_modf (mpfr-float-ref integral
)
1724 (mpfr-float-ref fractional
)
1727 (values integral fractional i
)))
1729 (defun fmod (x y
&optional
(round *mpfr-rnd
*))
1730 (let* ((result (make-mpfr-float))
1731 (i (mpfr_fmod (mpfr-float-ref result
)
1737 (defun remainder (x y
&optional
(round *mpfr-rnd
*))
1738 (let* ((result (make-mpfr-float))
1739 (i (mpfr_remainder (mpfr-float-ref result
)
1745 (defun remainder-quot (x y
&optional
(round *mpfr-rnd
*))
1746 (with-alien ((q long
))
1747 (let* ((result (make-mpfr-float))
1748 (i (mpfr_remquo (mpfr-float-ref result
)
1753 (values result q i
))))
1758 (declaim (inline mpfr_fits_ulong_p mpfr_fits_slong_p
))
1760 (define-alien-routine mpfr_fits_ulong_p boolean
1761 (x (* (struct mpfrfloat
)))
1762 (rnd mpfr_rnd_enum
))
1764 (define-alien-routine mpfr_fits_slong_p boolean
1765 (x (* (struct mpfrfloat
)))
1766 (rnd mpfr_rnd_enum
))
1768 (defun coerce (x type
&optional
(round *mpfr-rnd
*))
1770 ((typep x
'mpfr-float
)
1771 (let ((x-ref (mpfr-float-ref x
)))
1774 (mpfr_get_flt x-ref round
))
1776 (mpfr_get_d x-ref round
))
1778 (let ((result (make-mpfr-float)))
1779 (mpfr_set (mpfr-float-ref result
) x-ref round
)
1783 (error "Cannot coerce ~s to ~s. Argument must be an actual number."
1786 ((mpfr_fits_slong_p x-ref round
)
1787 (mpfr_get_si x-ref round
))
1788 ((mpfr_fits_ulong_p x-ref round
)
1789 (mpfr_get_ui x-ref round
))
1791 (sb-gmp::with-gmp-mpz-results
(rop)
1792 (mpfr_get_z (addr rop
) x-ref round
)))))
1794 (error "TYPE must be one of SINGLE-FLOAT, DOUBLE-FLOAT or INTEGER.")))))
1795 ((eql type
'mpfr-float
)
1796 (let ((result (make-mpfr-float)))
1798 ((signed-byte #.sb-vm
:n-word-bits
)
1799 (mpfr_set_si (mpfr-float-ref result
) x round
))
1800 ((unsigned-byte #.sb-vm
:n-word-bits
)
1801 (mpfr_set_ui (mpfr-float-ref result
) x round
))
1803 (sb-gmp::with-mpz-vars
((x gx
))
1804 (mpfr_set_z (mpfr-float-ref result
) (addr gx
) round
)))
1806 (mpfr_set_flt (mpfr-float-ref result
) x round
))
1808 (mpfr_set_d (mpfr-float-ref result
) x round
))
1810 (sb-gmp::with-mpq-var
(x qx
)
1811 (mpfr_set_q (mpfr-float-ref result
) (addr qx
) round
))))
1814 (error "Unable to handle the combination of ~S and ~S." x type
))))