2 (:use
"COMMON-LISP" "SB-ALIEN")
11 ;; +mpfr-precision+ is a pseudo-constant
12 ;; Do not set via LET but use the two methods below!
16 ;; parameters and types
20 ;; arithmetic operations
22 #:mpfr-float-to-string
83 #:arithmetic-geometric-mean
88 ;; comparison functions and predicates
110 ;; miscellaneous functions
119 #:set-div-by-zero-flag
130 ;; random number generation
135 #:rounded-int-ceiling
138 #:rounded-int-truncate
185 (in-package :sb-mpfr
)
186 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
187 (setf (sb-int:system-package-p
*package
*) t
))
189 (defvar +mpfr-precision
+)
190 (defvar *mpfr-version
* nil
)
191 (defvar *mpfr-features
* nil
)
193 (defun try-load-shared-object (pathname)
195 (load-shared-object pathname
:dont-save t
)
200 (or (some #'try-load-shared-object
201 #-
(or win32 darwin
) '("libmpfr.so" "libmpfr.so.4" "libmpfr.so.6")
202 #+darwin
'("libmpfr.dylib" "libmpfr.4.dylib" "libmpfr.6.dylib" #+arm64
"/opt/homebrew/lib/libmpfr.dylib")
203 #+win32
'("mpfr.dll" "libmpfr-6.dll"))
204 (warn "MPFR was not loaded. This is likely because the shared library ~
207 (defun load-mpfr (&key
(persistently t
))
208 (setf *mpfr-version
* nil
210 *features
* (set-difference *features
* '(:sb-mpfr
)))
212 (pushnew 'load-mpfr sb-ext
:*init-hooks
*)
213 ;(pushnew 'uninstall-mpfr-funs sb-ext:*save-hooks*)
215 (let ((success (%load-mpfr
)))
218 (alien-funcall (extern-alien "mpfr_get_version"
219 (function c-string
)))))
220 (cond ((null *mpfr-version
*))
221 ((string<= *mpfr-version
* "4.0.0")
222 (warn "SB-MPFR requires at least MPFR version 4.0.0")
225 (setf +mpfr-precision
+
226 (alien-funcall (extern-alien "mpfr_get_default_prec"
228 (pushnew :sb-mpfr
*mpfr-features
*)
229 (setf *features
* (union *features
* *mpfr-features
*))))
234 ;;; types and initialization
236 (define-alien-type nil
241 (mpfr_d (* gmp-limb
))))
243 (define-alien-type mpfr_rnd_enum
253 (declaim (inline mpfr_init2
265 mpfr_set_default_prec
268 (define-alien-routine mpfr_init2 void
269 (x (* (struct mpfrfloat
)))
272 (define-alien-routine mpfr_clear void
273 (x (* (struct mpfrfloat
))))
275 ;;; conversion functions
277 (define-alien-routine mpfr_set void
278 (x (* (struct mpfrfloat
)))
279 (op (* (struct mpfrfloat
)))
282 (define-alien-routine mpfr_set_ui void
283 (x (* (struct mpfrfloat
)))
287 (define-alien-routine mpfr_set_si void
288 (x (* (struct mpfrfloat
)))
292 (define-alien-routine mpfr_set_flt void
293 (x (* (struct mpfrfloat
)))
297 (define-alien-routine mpfr_set_d void
298 (x (* (struct mpfrfloat
)))
302 (define-alien-routine mpfr_set_z void
303 (x (* (struct mpfrfloat
)))
304 (op (* (struct sb-gmp
::gmpint
)))
307 (define-alien-routine mpfr_set_q void
308 (x (* (struct mpfrfloat
)))
309 (op (* (struct sb-gmp
::gmprat
)))
312 (define-alien-routine mpfr_set_nan void
313 (x (* (struct mpfrfloat
))))
315 (define-alien-routine mpfr_set_inf void
316 (x (* (struct mpfrfloat
)))
319 (define-alien-routine mpfr_set_zero void
320 (x (* (struct mpfrfloat
)))
323 (define-alien-routine mpfr_set_default_prec void
326 (define-alien-routine mpfr_get_str
(* char
)
331 (x (* (struct mpfrfloat
)))
334 ;;; conversion functions
336 (declaim (inline mpfr_get_flt
344 (define-alien-routine mpfr_get_flt float
345 (op (* (struct mpfrfloat
)))
348 (define-alien-routine mpfr_get_d double
349 (op (* (struct mpfrfloat
)))
352 (define-alien-routine mpfr_get_si long
353 (op (* (struct mpfrfloat
)))
356 (define-alien-routine mpfr_get_ui unsigned-long
357 (op (* (struct mpfrfloat
)))
360 (define-alien-routine mpfr_get_z int
361 (res (* (struct sb-gmp
::gmpint
)))
362 (op (* (struct mpfrfloat
)))
365 (define-alien-routine mpfr_free_str void
368 (define-alien-routine mpfr_set_str int
369 (x (* (struct mpfrfloat
)))
374 ;;; arithmetic functions
376 (declaim (inline mpfr_add
426 (define-alien-routine mpfr_add int
427 (r (* (struct mpfrfloat
)))
428 (op1 (* (struct mpfrfloat
)))
429 (op2 (* (struct mpfrfloat
)))
432 (define-alien-routine mpfr_add_ui int
433 (r (* (struct mpfrfloat
)))
434 (op1 (* (struct mpfrfloat
)))
438 (define-alien-routine mpfr_add_si int
439 (r (* (struct mpfrfloat
)))
440 (op1 (* (struct mpfrfloat
)))
444 (define-alien-routine mpfr_add_d int
445 (r (* (struct mpfrfloat
)))
446 (op1 (* (struct mpfrfloat
)))
450 (define-alien-routine mpfr_add_z int
451 (r (* (struct mpfrfloat
)))
452 (op1 (* (struct mpfrfloat
)))
453 (op2 (* (struct sb-gmp
::gmpint
)))
456 (define-alien-routine mpfr_add_q int
457 (r (* (struct mpfrfloat
)))
458 (op1 (* (struct mpfrfloat
)))
459 (op2 (* (struct sb-gmp
::gmprat
)))
462 (define-alien-routine mpfr_sub int
463 (r (* (struct mpfrfloat
)))
464 (op1 (* (struct mpfrfloat
)))
465 (op2 (* (struct mpfrfloat
)))
468 (define-alien-routine mpfr_ui_sub int
469 (r (* (struct mpfrfloat
)))
471 (op2 (* (struct mpfrfloat
)))
474 (define-alien-routine mpfr_sub_ui int
475 (r (* (struct mpfrfloat
)))
476 (op1 (* (struct mpfrfloat
)))
480 (define-alien-routine mpfr_si_sub int
481 (r (* (struct mpfrfloat
)))
483 (op2 (* (struct mpfrfloat
)))
486 (define-alien-routine mpfr_sub_si int
487 (r (* (struct mpfrfloat
)))
488 (op1 (* (struct mpfrfloat
)))
492 (define-alien-routine mpfr_d_sub int
493 (r (* (struct mpfrfloat
)))
495 (op2 (* (struct mpfrfloat
)))
498 (define-alien-routine mpfr_sub_d int
499 (r (* (struct mpfrfloat
)))
500 (op1 (* (struct mpfrfloat
)))
504 (define-alien-routine mpfr_z_sub int
505 (r (* (struct mpfrfloat
)))
506 (op1 (* (struct sb-gmp
::gmpint
)))
507 (op2 (* (struct mpfrfloat
)))
510 (define-alien-routine mpfr_sub_z int
511 (r (* (struct mpfrfloat
)))
512 (op1 (* (struct mpfrfloat
)))
513 (op2 (* (struct sb-gmp
::gmpint
)))
516 (define-alien-routine mpfr_sub_q int
517 (r (* (struct mpfrfloat
)))
518 (op1 (* (struct mpfrfloat
)))
519 (op2 (* (struct sb-gmp
::gmprat
)))
522 (define-alien-routine mpfr_mul int
523 (r (* (struct mpfrfloat
)))
524 (op1 (* (struct mpfrfloat
)))
525 (op2 (* (struct mpfrfloat
)))
528 (define-alien-routine mpfr_mul_ui int
529 (r (* (struct mpfrfloat
)))
530 (op1 (* (struct mpfrfloat
)))
534 (define-alien-routine mpfr_mul_si int
535 (r (* (struct mpfrfloat
)))
536 (op1 (* (struct mpfrfloat
)))
540 (define-alien-routine mpfr_mul_d int
541 (r (* (struct mpfrfloat
)))
542 (op1 (* (struct mpfrfloat
)))
546 (define-alien-routine mpfr_mul_z int
547 (r (* (struct mpfrfloat
)))
548 (op1 (* (struct mpfrfloat
)))
549 (op2 (* (struct sb-gmp
::gmpint
)))
552 (define-alien-routine mpfr_mul_q int
553 (r (* (struct mpfrfloat
)))
554 (op1 (* (struct mpfrfloat
)))
555 (op2 (* (struct sb-gmp
::gmprat
)))
558 (define-alien-routine mpfr_sqr int
559 (r (* (struct mpfrfloat
)))
560 (op (* (struct mpfrfloat
)))
563 (define-alien-routine mpfr_div int
564 (r (* (struct mpfrfloat
)))
565 (op1 (* (struct mpfrfloat
)))
566 (op2 (* (struct mpfrfloat
)))
569 (define-alien-routine mpfr_ui_div int
570 (r (* (struct mpfrfloat
)))
572 (op2 (* (struct mpfrfloat
)))
575 (define-alien-routine mpfr_div_ui int
576 (r (* (struct mpfrfloat
)))
577 (op1 (* (struct mpfrfloat
)))
581 (define-alien-routine mpfr_si_div int
582 (r (* (struct mpfrfloat
)))
584 (op2 (* (struct mpfrfloat
)))
587 (define-alien-routine mpfr_div_si int
588 (r (* (struct mpfrfloat
)))
589 (op1 (* (struct mpfrfloat
)))
593 (define-alien-routine mpfr_d_div int
594 (r (* (struct mpfrfloat
)))
596 (op2 (* (struct mpfrfloat
)))
599 (define-alien-routine mpfr_div_d int
600 (r (* (struct mpfrfloat
)))
601 (op1 (* (struct mpfrfloat
)))
605 (define-alien-routine mpfr_div_z int
606 (r (* (struct mpfrfloat
)))
607 (op1 (* (struct mpfrfloat
)))
608 (op2 (* (struct sb-gmp
::gmpint
)))
611 (define-alien-routine mpfr_div_q int
612 (r (* (struct mpfrfloat
)))
613 (op1 (* (struct mpfrfloat
)))
614 (op2 (* (struct sb-gmp
::gmprat
)))
617 (define-alien-routine mpfr_sqrt int
618 (r (* (struct mpfrfloat
)))
619 (op (* (struct mpfrfloat
)))
622 (define-alien-routine mpfr_sqrt_ui int
623 (r (* (struct mpfrfloat
)))
627 (define-alien-routine mpfr_rec_sqrt int
628 (r (* (struct mpfrfloat
)))
629 (op (* (struct mpfrfloat
)))
632 (define-alien-routine mpfr_cbrt int
633 (r (* (struct mpfrfloat
)))
634 (op (* (struct mpfrfloat
)))
637 (define-alien-routine mpfr_root int
638 (r (* (struct mpfrfloat
)))
639 (op (* (struct mpfrfloat
)))
643 (define-alien-routine mpfr_pow int
644 (r (* (struct mpfrfloat
)))
645 (op1 (* (struct mpfrfloat
)))
646 (op2 (* (struct mpfrfloat
)))
649 (define-alien-routine mpfr_pow_ui int
650 (r (* (struct mpfrfloat
)))
651 (op1 (* (struct mpfrfloat
)))
655 (define-alien-routine mpfr_pow_si int
656 (r (* (struct mpfrfloat
)))
657 (op1 (* (struct mpfrfloat
)))
661 (define-alien-routine mpfr_pow_z int
662 (r (* (struct mpfrfloat
)))
663 (op1 (* (struct mpfrfloat
)))
664 (op2 (* (struct sb-gmp
::gmpint
)))
667 (define-alien-routine mpfr_ui_pow int
668 (r (* (struct mpfrfloat
)))
670 (op2 (* (struct mpfrfloat
)))
673 (define-alien-routine mpfr_neg int
674 (r (* (struct mpfrfloat
)))
675 (op (* (struct mpfrfloat
)))
678 (define-alien-routine mpfr_abs int
679 (r (* (struct mpfrfloat
)))
680 (op (* (struct mpfrfloat
)))
683 (define-alien-routine mpfr_dim int
684 (r (* (struct mpfrfloat
)))
685 (op1 (* (struct mpfrfloat
)))
686 (op2 (* (struct mpfrfloat
)))
689 (define-alien-routine mpfr_mul_2ui int
690 (r (* (struct mpfrfloat
)))
691 (op1 (* (struct mpfrfloat
)))
695 (define-alien-routine mpfr_mul_2si int
696 (r (* (struct mpfrfloat
)))
697 (op1 (* (struct mpfrfloat
)))
701 (define-alien-routine mpfr_div_2ui int
702 (r (* (struct mpfrfloat
)))
703 (op1 (* (struct mpfrfloat
)))
707 (define-alien-routine mpfr_div_2si int
708 (r (* (struct mpfrfloat
)))
709 (op1 (* (struct mpfrfloat
)))
713 ;;; special functions
715 (defmacro define-onearg-mpfr-int
(funs)
716 (loop for i in funs collect
`(define-alien-routine ,i int
717 (r (* (struct mpfrfloat
)))
718 (op (* (struct mpfrfloat
)))
721 finally
(return `(progn
722 (declaim (inline ,@funs
))
725 (define-onearg-mpfr-int
766 (defmacro define-twoarg-mpfr-int
(funs)
767 (loop for i in funs collect
`(define-alien-routine ,i int
768 (r (* (struct mpfrfloat
)))
769 (op1 (* (struct mpfrfloat
)))
770 (op2 (* (struct mpfrfloat
)))
773 finally
(return `(progn
774 (declaim (inline ,@funs
))
777 (define-twoarg-mpfr-int
784 (declaim (inline mpfr_fac_ui
791 (define-alien-routine mpfr_fac_ui int
792 (r (* (struct mpfrfloat
)))
796 (define-alien-routine mpfr_zeta_ui int
797 (r (* (struct mpfrfloat
)))
801 (define-alien-routine mpfr_jn int
802 (r (* (struct mpfrfloat
)))
804 (op (* (struct mpfrfloat
)))
807 (define-alien-routine mpfr_yn int
808 (r (* (struct mpfrfloat
)))
810 (op (* (struct mpfrfloat
)))
813 (define-alien-routine mpfr_fma int
814 (r (* (struct mpfrfloat
)))
815 (op1 (* (struct mpfrfloat
)))
816 (op2 (* (struct mpfrfloat
)))
817 (op3 (* (struct mpfrfloat
)))
820 (define-alien-routine mpfr_fms int
821 (r (* (struct mpfrfloat
)))
822 (op1 (* (struct mpfrfloat
)))
823 (op2 (* (struct mpfrfloat
)))
824 (op3 (* (struct mpfrfloat
)))
828 ;;; constant initialization
830 (defmacro define-const-mpfr-int
(funs)
831 (loop for i in funs collect
`(define-alien-routine ,i int
832 (r (* (struct mpfrfloat
)))
835 finally
(return `(progn
836 (declaim (inline ,@funs
))
839 (define-const-mpfr-int
845 (declaim (inline mpfr_sum
))
846 (define-alien-routine mpfr_sum int
847 (r (* (struct mpfrfloat
)))
848 (tab (* (* (struct mpfrfloat
))))
853 ;;; comparison functions
855 (declaim (inline mpfr_cmp
865 (define-alien-routine mpfr_cmp int
866 (op1 (* (struct mpfrfloat
)))
867 (op2 (* (struct mpfrfloat
))))
869 (define-alien-routine mpfr_cmp_ui int
870 (op1 (* (struct mpfrfloat
)))
873 (define-alien-routine mpfr_cmp_si int
874 (op1 (* (struct mpfrfloat
)))
877 (define-alien-routine mpfr_cmp_d int
878 (op1 (* (struct mpfrfloat
)))
881 (define-alien-routine mpfr_cmp_z int
882 (op1 (* (struct mpfrfloat
)))
883 (op2 (* (struct sb-gmp
::gmpint
))))
885 (define-alien-routine mpfr_cmp_q int
886 (op1 (* (struct mpfrfloat
)))
887 (op2 (* (struct sb-gmp
::gmprat
))))
889 (define-alien-routine mpfr_cmp_ui_2exp int
890 (op1 (* (struct mpfrfloat
)))
894 (define-alien-routine mpfr_cmp_si_2exp int
895 (op1 (* (struct mpfrfloat
)))
899 (define-alien-routine mpfr_cmpabs int
900 (op1 (* (struct mpfrfloat
)))
901 (op2 (* (struct mpfrfloat
))))
904 (defmacro define-onearg-mpfr-bool
(funs)
905 (loop for i in funs collect
`(define-alien-routine ,i boolean
906 (op (* (struct mpfrfloat
))))
908 finally
(return `(progn
909 (declaim (inline ,@funs
))
912 (define-onearg-mpfr-bool
920 (declaim (inline mpfr_sgn
))
921 (define-alien-routine mpfr_sgn int
922 (op (* (struct mpfrfloat
))))
924 (defmacro define-twoarg-mpfr-bool
(funs)
925 (loop for i in funs collect
`(define-alien-routine ,i boolean
926 (op1 (* (struct mpfrfloat
)))
927 (op2 (* (struct mpfrfloat
))))
929 finally
(return `(progn
930 (declaim (inline ,@funs
))
933 (define-twoarg-mpfr-bool
943 ;;; miscellaneous functions
945 (defmacro define-mpfr-void
(funs)
946 (loop for i in funs collect
`(define-alien-routine ,i void
)
948 finally
(return `(progn
949 (declaim (inline ,@funs
))
953 (mpfr_clear_underflow
958 mpfr_clear_erangeflag
967 (defmacro define-mpfr-bool
(funs)
968 (loop for i in funs collect
`(define-alien-routine ,i boolean
)
970 finally
(return `(progn
971 (declaim (inline ,@funs
))
983 (declaim (inline mpfr_urandomb
986 (define-alien-routine mpfr_urandomb int
987 (op (* (struct mpfrfloat
)))
988 (s (* (struct sb-gmp
::gmprandstate
))))
990 (define-alien-routine mpfr_urandom int
991 (op (* (struct mpfrfloat
)))
992 (s (* (struct sb-gmp
::gmprandstate
)))
996 ;;; integer and remainder related functions / rounding
998 (define-onearg-mpfr-int
1006 (declaim (inline mpfr_ceil
1015 (define-alien-routine mpfr_ceil int
1016 (r (* (struct mpfrfloat
)))
1017 (op (* (struct mpfrfloat
))))
1019 (define-alien-routine mpfr_floor int
1020 (r (* (struct mpfrfloat
)))
1021 (op (* (struct mpfrfloat
))))
1023 (define-alien-routine mpfr_round int
1024 (r (* (struct mpfrfloat
)))
1025 (op (* (struct mpfrfloat
))))
1027 (define-alien-routine mpfr_trunc int
1028 (r (* (struct mpfrfloat
)))
1029 (op (* (struct mpfrfloat
))))
1031 (define-alien-routine mpfr_modf int
1032 (ir (* (struct mpfrfloat
)))
1033 (fr (* (struct mpfrfloat
)))
1034 (op (* (struct mpfrfloat
)))
1035 (rnd mpfr_rnd_enum
))
1037 (define-alien-routine mpfr_fmod int
1038 (r (* (struct mpfrfloat
)))
1039 (x (* (struct mpfrfloat
)))
1040 (y (* (struct mpfrfloat
)))
1041 (rnd mpfr_rnd_enum
))
1043 (define-alien-routine mpfr_remainder int
1044 (r (* (struct mpfrfloat
)))
1045 (x (* (struct mpfrfloat
)))
1046 (y (* (struct mpfrfloat
)))
1047 (rnd mpfr_rnd_enum
))
1049 (define-alien-routine mpfr_remquo int
1050 (r (* (struct mpfrfloat
)))
1052 (x (* (struct mpfrfloat
)))
1053 (y (* (struct mpfrfloat
)))
1054 (rnd mpfr_rnd_enum
))
1059 (defparameter *mpfr-rnd
* :mpfr_rndn
)
1060 (defparameter *mpfr-base
* 10)
1062 (declaim (inline mpfr-float-ref
1065 (defstruct (mpfr-float (:constructor %make-mpfr-float
))
1066 (ref (make-alien (struct mpfrfloat
))
1067 :type
(alien (* (struct mpfrfloat
))) :read-only t
))
1069 (defun make-mpfr-float (&optional
(precision +mpfr-precision
+))
1070 (declare (optimize (speed 3) (space 3)))
1071 (let* ((float (%make-mpfr-float
))
1072 (ref (mpfr-float-ref float
)))
1073 (mpfr_init2 ref precision
)
1074 (sb-ext:finalize float
(lambda ()
1075 (declare (optimize (speed 3) (space 3) (safety 0)))
1080 (defmacro with-precision
(value &body body
)
1081 `(let* ((old +mpfr-precision
+)
1082 (+mpfr-precision
+ ,value
))
1085 (mpfr_set_default_prec ,value
)
1087 (mpfr_set_default_prec old
))))
1089 (defun set-precision (value)
1090 (check-type value ui
)
1091 (mpfr_set_default_prec value
)
1092 (setf +mpfr-precision
+ value
))
1094 ;;; printing and reader syntax
1096 (defmethod print-object ((obj mpfr-float
) stream
)
1097 (multiple-value-bind (str exp sign
)
1098 (mpfr-float-to-string obj
)
1099 (declare (type (integer -
1 1) sign
))
1100 (cond (*print-readably
*
1101 (write-char #\
# stream
)
1102 (write-char #\M stream
)
1103 (write-string str stream
)
1104 (write-char #\
@ stream
)
1106 (1 (princ (- exp
(length str
)) stream
))
1107 (-1 (princ (- exp
(1- (length str
))) stream
))))
1111 (write-char #\
0 stream
))
1113 (write-char #\. stream
)
1114 (write-string str stream
))
1116 (write-char #\- stream
)
1117 (write-char #\. stream
)
1118 (write-string str stream
:start
1)))
1119 (write-char #\e stream
)
1120 (princ exp stream
)))))
1122 (defun mpfr-float-to-string (x &optional
(rnd *mpfr-rnd
*))
1123 (let ((xr (mpfr-float-ref x
)))
1124 (with-alien ((exp long
)
1127 (setf str
(mpfr_get_str NIL
(addr exp
) *print-base
* 0 xr rnd
))
1128 (multiple-value-prog1
1129 (values (cast str c-string
) exp
(mpfr_cmp_ui xr
0))
1130 (mpfr_free_str str
)))))
1132 (defun mpfr-reader (stream subchar arg
)
1133 (declare (ignore subchar arg
))
1134 (let ((mpfr (make-mpfr-float)))
1135 (mpfr_set_str (mpfr-float-ref mpfr
)
1136 (let ((peek (peek-char t stream nil nil t
)))
1137 (if (char= peek
#\") ;; The old lazy way
1138 (read stream nil nil t
)
1139 (with-output-to-string (str)
1140 (loop for char
= (peek-char nil stream nil nil t
)
1142 (not (sb-impl:token-delimiterp char
)))
1143 do
(write-char (read-char stream nil nil t
) str
)))))
1144 *mpfr-base
* *mpfr-rnd
*)
1147 (defun enable-mpfr-syntax (readtable)
1148 (set-dispatch-macro-character #\
# #\M
#'mpfr-reader readtable
))
1149 (enable-mpfr-syntax *readtable
*)
1152 ;;; arithmetic functions
1154 (defun add (x y
&optional
(round *mpfr-rnd
*))
1155 (if (typep x
'mpfr-float
)
1156 (let* ((res (make-mpfr-float))
1157 (r (mpfr-float-ref res
))
1158 (xr (mpfr-float-ref x
))
1161 (mpfr_add r xr
(mpfr-float-ref y
) round
))
1163 (mpfr_add_ui r xr y round
))
1165 (mpfr_add_si r xr y round
))
1167 (mpfr_add_d r xr y round
))
1169 (sb-gmp::with-mpz-vars
((y gy
))
1170 (mpfr_add_z r xr
(addr gy
) round
)))
1172 (sb-gmp::with-mpq-var
(y qy
)
1173 (mpfr_add_q r xr
(addr qy
) round
))))))
1179 (defun sub (x y
&optional
(round *mpfr-rnd
*))
1180 (let* ((res (make-mpfr-float))
1181 (r (mpfr-float-ref res
))
1184 (let ((xr (mpfr-float-ref x
)))
1187 (mpfr_sub r xr
(mpfr-float-ref y
) round
))
1189 (mpfr_sub_ui r xr y round
))
1191 (mpfr_sub_si r xr y round
))
1193 (mpfr_sub_d r xr y round
))
1195 (sb-gmp::with-mpz-vars
((y gy
))
1196 (mpfr_sub_z r xr
(addr gy
) round
)))
1198 (sb-gmp::with-mpq-var
(y qy
)
1199 (mpfr_sub_q r xr
(addr qy
) round
))))))
1203 (mpfr_ui_sub r x
(mpfr-float-ref y
) round
))))
1207 (mpfr_si_sub r x
(mpfr-float-ref y
) round
))))
1211 (mpfr_d_sub r x
(mpfr-float-ref y
) round
))))
1215 (sb-gmp::with-mpz-vars
((x gx
))
1216 (mpfr_z_sub r
(addr gx
) (mpfr-float-ref y
) round
))))))))
1219 (defun mul (x y
&optional
(round *mpfr-rnd
*))
1220 (if (typep x
'mpfr-float
)
1221 (let* ((res (make-mpfr-float))
1222 (r (mpfr-float-ref res
))
1223 (xr (mpfr-float-ref x
))
1226 (mpfr_mul r xr
(mpfr-float-ref y
) round
))
1228 (mpfr_mul_ui r xr y round
))
1230 (mpfr_mul_si r xr y round
))
1232 (mpfr_mul_d r xr y round
))
1234 (sb-gmp::with-mpz-vars
((y gy
))
1235 (mpfr_mul_z r xr
(addr gy
) round
)))
1237 (sb-gmp::with-mpq-var
(y qy
)
1238 (mpfr_mul_q r xr
(addr qy
) round
))))))
1244 (defun square (x &optional
(round *mpfr-rnd
*))
1245 (let ((r (make-mpfr-float)))
1246 (values r
(mpfr_sqr (mpfr-float-ref r
) (mpfr-float-ref x
) round
))))
1248 (defun div (x y
&optional
(round *mpfr-rnd
*))
1249 (let* ((res (make-mpfr-float))
1250 (r (mpfr-float-ref res
))
1253 (let ((xr (mpfr-float-ref x
)))
1256 (mpfr_div r xr
(mpfr-float-ref y
) round
))
1258 (mpfr_div_ui r xr y round
))
1260 (mpfr_div_si r xr y round
))
1262 (mpfr_div_d r xr y round
))
1264 (sb-gmp::with-mpz-vars
((y gy
))
1265 (mpfr_div_z r xr
(addr gy
) round
)))
1267 (sb-gmp::with-mpq-var
(y qy
)
1268 (mpfr_div_q r xr
(addr qy
) round
))))))
1272 (mpfr_ui_div r x
(mpfr-float-ref y
) round
))))
1276 (mpfr_si_div r x
(mpfr-float-ref y
) round
))))
1280 (mpfr_d_div r x
(mpfr-float-ref y
) round
)))))))
1283 (defun sqrt (x &optional
(round *mpfr-rnd
*))
1284 (let* ((res (make-mpfr-float))
1285 (r (mpfr-float-ref res
))
1288 (mpfr_sqrt_ui r x round
))
1290 (mpfr_sqrt r
(mpfr-float-ref x
) round
)))))
1293 (defun reciprocal-sqrt (x &optional
(round *mpfr-rnd
*))
1294 (let* ((res (make-mpfr-float))
1295 (r (mpfr-float-ref res
))
1296 (i (mpfr_rec_sqrt r
(mpfr-float-ref x
) round
)))
1299 (defun cubic-root (x &optional
(round *mpfr-rnd
*))
1300 (let* ((res (make-mpfr-float))
1301 (r (mpfr-float-ref res
))
1302 (i (mpfr_cbrt r
(mpfr-float-ref x
) round
)))
1305 (defun k-root (x k
&optional
(round *mpfr-rnd
*))
1307 (let* ((res (make-mpfr-float))
1308 (r (mpfr-float-ref res
))
1309 (i (mpfr_root r
(mpfr-float-ref x
) k round
)))
1312 (defun power (x y
&optional
(round *mpfr-rnd
*))
1313 (let* ((res (make-mpfr-float))
1314 (r (mpfr-float-ref res
))
1317 (let ((xr (mpfr-float-ref x
)))
1320 (mpfr_pow r xr
(mpfr-float-ref y
) round
))
1322 (mpfr_pow_ui r xr y round
))
1324 (mpfr_pow_si r xr y round
))
1326 (sb-gmp::with-mpz-vars
((y gy
))
1327 (mpfr_pow_z r xr
(addr gy
) round
))))))
1331 (mpfr_ui_pow r x
(mpfr-float-ref y
) round
)))))))
1334 (defun negate (x &optional
(round *mpfr-rnd
*))
1335 (let* ((res (make-mpfr-float))
1336 (r (mpfr-float-ref res
))
1337 (i (mpfr_neg r
(mpfr-float-ref x
) round
)))
1340 (defun abs (x &optional
(round *mpfr-rnd
*))
1341 (let* ((res (make-mpfr-float))
1342 (r (mpfr-float-ref res
))
1343 (i (mpfr_abs r
(mpfr-float-ref x
) round
)))
1346 (defun dim (x y
&optional
(round *mpfr-rnd
*))
1347 (let* ((res (make-mpfr-float))
1348 (r (mpfr-float-ref res
))
1349 (i (mpfr_dim r
(mpfr-float-ref x
) (mpfr-float-ref y
) round
)))
1352 (defun mul-2-raised (x y
&optional
(round *mpfr-rnd
*))
1354 (let* ((res (make-mpfr-float))
1355 (r (mpfr-float-ref res
))
1358 (mpfr_mul_2ui r
(mpfr-float-ref x
) y round
))
1360 (mpfr_mul_2si r
(mpfr-float-ref x
) y round
)))))
1363 (defun div-2-raised (x y
&optional
(round *mpfr-rnd
*))
1365 (let* ((res (make-mpfr-float))
1366 (r (mpfr-float-ref res
))
1369 (mpfr_div_2ui r
(mpfr-float-ref x
) y round
))
1371 (mpfr_div_2si r
(mpfr-float-ref x
) y round
)))))
1374 ;;; special functions
1376 (defmacro define-onearg-mpfr-funs
(funs)
1377 (loop for
(clfun mfun
) in funs
1378 collect
`(defun ,clfun
(x &optional
(round *mpfr-rnd
*))
1379 (let* ((result (make-mpfr-float))
1380 (i (,mfun
(mpfr-float-ref result
)
1385 finally
(return `(progn
1388 (define-onearg-mpfr-funs
1417 (lngamma mpfr_lngamma
)
1418 (digamma mpfr_digamma
)
1427 (defun atan (y &optional x
(round *mpfr-rnd
*))
1429 (let* ((result (make-mpfr-float))
1430 (i (mpfr_atan2 (mpfr-float-ref result
)
1435 (let* ((result (make-mpfr-float))
1436 (i (mpfr_atan (mpfr-float-ref result
)
1439 (values result i
))))
1441 (defun sin-cos (x &optional
(round *mpfr-rnd
*))
1442 (let* ((sin (make-mpfr-float))
1443 (cos (make-mpfr-float))
1444 (i (mpfr_sin_cos (mpfr-float-ref sin
)
1445 (mpfr-float-ref cos
)
1448 (values sin cos i
)))
1450 (defun sinh-cosh (x &optional
(round *mpfr-rnd
*))
1451 (let* ((sin (make-mpfr-float))
1452 (cos (make-mpfr-float))
1453 (i (mpfr_sinh_cosh (mpfr-float-ref sin
)
1454 (mpfr-float-ref cos
)
1457 (values sin cos i
)))
1459 (defun arithmetic-geometric-mean (u v
&optional
(round *mpfr-rnd
*))
1460 (let* ((result (make-mpfr-float))
1461 (i (mpfr_agm (mpfr-float-ref result
)
1467 (defun hypot (x y
&optional
(round *mpfr-rnd
*))
1468 (let* ((result (make-mpfr-float))
1469 (i (mpfr_hypot (mpfr-float-ref result
)
1475 (defun fac (x &optional
(round *mpfr-rnd
*))
1476 (let* ((result (make-mpfr-float))
1477 (i (mpfr_fac_ui (mpfr-float-ref result
)
1482 (defun zeta (x &optional
(round *mpfr-rnd
*))
1483 (let* ((result (make-mpfr-float))
1486 (mpfr_zeta (mpfr-float-ref result
)
1490 (mpfr_zeta_ui (mpfr-float-ref result
)
1495 (defun jn (n x
&optional
(round *mpfr-rnd
*))
1497 (let* ((result (make-mpfr-float))
1498 (i (mpfr_jn (mpfr-float-ref result
)
1504 (defun yn (n x
&optional
(round *mpfr-rnd
*))
1506 (let* ((result (make-mpfr-float))
1507 (i (mpfr_yn (mpfr-float-ref result
)
1513 (defun fma (x y z
&optional
(round *mpfr-rnd
*))
1514 "fma X Y Z = (X * Y) + Z"
1515 (let* ((result (make-mpfr-float))
1516 (i (mpfr_fma (mpfr-float-ref result
)
1523 (defun fms (x y z
&optional
(round *mpfr-rnd
*))
1524 "fma X Y Z = (X * Y) - Z"
1525 (let* ((result (make-mpfr-float))
1526 (i (mpfr_fms (mpfr-float-ref result
)
1533 (defun sum (seq &optional
(round *mpfr-rnd
*))
1534 (let ((length (length seq
))
1536 (declare (type (integer -
1 #.most-positive-fixnum
) idx
))
1537 (let ((result (make-mpfr-float))
1538 (ar (make-alien (* (struct mpfrfloat
)) length
)))
1541 (map nil
(lambda (x)
1542 (setf (deref ar
(incf idx
))
1543 (mpfr-float-ref x
)))
1545 (let ((i (mpfr_sum (mpfr-float-ref result
)
1555 (defmacro define-const-mpfr-funs
(funs)
1556 (loop for
(fname mname
) in funs
1557 collect
`(defun ,fname
(&optional
(round *mpfr-rnd
*))
1558 (let* ((result (make-mpfr-float))
1559 (i (,mname
(mpfr-float-ref result
)
1563 finally
(return `(progn
1566 (define-const-mpfr-funs
1567 ((const-log2 mpfr_const_log2
)
1568 (const-pi mpfr_const_pi
)
1569 (const-euler mpfr_const_euler
)
1570 (const-catalan mpfr_const_catalan
)))
1572 ;;; comparison functions and predicates
1574 (defmacro define-onearg-mpfr-predicates
(funs)
1575 (loop for
(fname mname
) in funs
1576 collect
`(defun ,fname
(x)
1577 (,mname
(mpfr-float-ref x
)))
1579 finally
(return `(progn
1582 (define-onearg-mpfr-predicates
1584 (infinityp mpfr_inf_p
)
1585 (numberp mpfr_number_p
)
1587 (integerp mpfr_integer_p
)
1588 (regularp mpfr_regular_p
)))
1590 (defmacro define-twoarg-mpfr-predicates
(funs)
1591 (loop for
(fname mname
) in funs
1592 collect
`(defun ,fname
(x y
)
1593 (,mname
(mpfr-float-ref x
)
1594 (mpfr-float-ref y
)))
1596 finally
(return `(progn
1599 (define-twoarg-mpfr-predicates
1600 ((compare-abs mpfr_cmpabs
)
1602 (>= mpfr_greaterequal_p
)
1604 (<= mpfr_lessequal_p
)
1606 (/= mpfr_lessgreater_p
)
1607 (unorderedp mpfr_unordered_p
)))
1609 (defun compare (x y
)
1610 (if (typep x
'mpfr-float
)
1613 (mpfr_cmp (mpfr-float-ref x
)
1614 (mpfr-float-ref y
)))
1616 (mpfr_cmp_ui (mpfr-float-ref x
) y
))
1618 (mpfr_cmp_si (mpfr-float-ref x
) y
))
1620 (mpfr_cmp_d (mpfr-float-ref x
) y
))
1622 (sb-gmp::with-mpz-vars
((y gy
))
1623 (mpfr_cmp_z (mpfr-float-ref x
) (addr gy
))))
1625 (sb-gmp::with-mpq-var
(y qy
)
1626 (mpfr_cmp_q (mpfr-float-ref x
) (addr qy
)))))
1631 (defun compare-2exp (x y exp
)
1632 (if (typep x
'mpfr-float
)
1635 (mpfr_cmp_ui_2exp (mpfr-float-ref x
) y exp
))
1637 (mpfr_cmp_si_2exp (mpfr-float-ref x
) y exp
)))
1640 (compare-2exp y x exp
)))))
1643 ;;; miscellaneous functions
1645 (defmacro define-mpfr-flag-funs
(funs)
1646 (loop for
(pname mname
) in funs
1647 collect
`(defun ,pname
()
1648 (declare (optimize (speed 3) (space 3)))
1651 collect pname into names
1652 finally
(return `(progn
1653 (declaim (inline ,@names
))
1656 (define-mpfr-flag-funs
1657 ((clear-underflow mpfr_clear_underflow
)
1658 (clear-overflow mpfr_clear_overflow
)
1659 (clear-div-by-zero mpfr_clear_divby0
)
1660 (clear-nan-flag mpfr_clear_nanflag
)
1661 (clear-inex-flag mpfr_clear_inexflag
)
1662 (clear-erange-flag mpfr_clear_erangeflag
)
1663 (set-underflow-flag mpfr_set_underflow
)
1664 (set-overflow-flag mpfr_set_overflow
)
1665 (set-div-by-zero-flag mpfr_set_divby0
)
1666 (set-nan-flag mpfr_set_nanflag
)
1667 (set-inex-flag mpfr_set_inexflag
)
1668 (set-erange-flag mpfr_set_erangeflag
)
1669 (clear-flags mpfr_clear_flags
)))
1672 (defmacro define-mpfr-flag-predicates
(funs)
1673 (loop for
(pname mname
) in funs
1674 collect
`(defun ,pname
()
1675 (declare (optimize (speed 3) (space 3)))
1678 collect pname into names
1679 finally
(return `(progn
1680 (declaim (inline ,@names
))
1683 (define-mpfr-flag-predicates
1684 ((underflowp mpfr_underflow_p
)
1685 (overflowp mpfr_overflow_p
)
1686 (div-by-zero-p mpfr_divby0_p
)
1687 (nanflag-p mpfr_nanflag_p
)
1688 (inexflag-p mpfr_inexflag_p
)
1689 (erangeflag-p mpfr_erangeflag_p
)))
1692 ;;; random number generation
1694 (defun urandomb (state)
1695 (check-type state sb-gmp
::gmp-rstate
)
1696 (let* ((ref (sb-gmp::gmp-rstate-ref state
))
1697 (result (make-mpfr-float))
1698 (i (mpfr_urandomb (mpfr-float-ref result
)
1702 (defun urandom (state &optional
(round *mpfr-rnd
*))
1703 (check-type state sb-gmp
::gmp-rstate
)
1704 (let* ((ref (sb-gmp::gmp-rstate-ref state
))
1705 (result (make-mpfr-float))
1706 (i (mpfr_urandom (mpfr-float-ref result
)
1712 ;;; integer and remainder related functions / rounding
1714 (define-onearg-mpfr-funs
1715 ((rounded-int mpfr_rint
)
1716 (rounded-int-ceiling mpfr_rint_ceil
)
1717 (rounded-int-floor mpfr_rint_floor
)
1718 (rounded-int-round mpfr_rint_round
)
1719 (rounded-int-truncate mpfr_rint_trunc
)
1720 (fractional mpfr_frac
)))
1722 (defmacro define-onearg-no-rnd-mpfr-funs
(funs)
1723 (loop for
(clfun mfun
) in funs
1724 collect
`(defun ,clfun
(x)
1725 (let* ((result (make-mpfr-float))
1726 (i (,mfun
(mpfr-float-ref result
)
1727 (mpfr-float-ref x
))))
1730 finally
(return `(progn
1733 (define-onearg-no-rnd-mpfr-funs
1734 ((ceiling mpfr_ceil
)
1737 (truncate mpfr_trunc
)))
1739 (defun modf (x &optional
(round *mpfr-rnd
*))
1740 (let* ((integral (make-mpfr-float))
1741 (fractional (make-mpfr-float))
1742 (i (mpfr_modf (mpfr-float-ref integral
)
1743 (mpfr-float-ref fractional
)
1746 (values integral fractional i
)))
1748 (defun fmod (x y
&optional
(round *mpfr-rnd
*))
1749 (let* ((result (make-mpfr-float))
1750 (i (mpfr_fmod (mpfr-float-ref result
)
1756 (defun remainder (x y
&optional
(round *mpfr-rnd
*))
1757 (let* ((result (make-mpfr-float))
1758 (i (mpfr_remainder (mpfr-float-ref result
)
1764 (defun remainder-quot (x y
&optional
(round *mpfr-rnd
*))
1765 (with-alien ((q long
))
1766 (let* ((result (make-mpfr-float))
1767 (i (mpfr_remquo (mpfr-float-ref result
)
1772 (values result q i
))))
1777 (declaim (inline mpfr_fits_ulong_p mpfr_fits_slong_p
))
1779 (define-alien-routine mpfr_fits_ulong_p boolean
1780 (x (* (struct mpfrfloat
)))
1781 (rnd mpfr_rnd_enum
))
1783 (define-alien-routine mpfr_fits_slong_p boolean
1784 (x (* (struct mpfrfloat
)))
1785 (rnd mpfr_rnd_enum
))
1787 (declaim (inline mpfr_get_q
))
1788 (define-alien-routine mpfr_get_q void
1789 (rop (* (struct sb-gmp
::gmprat
)))
1790 (op (* (struct mpfrfloat
))))
1792 (defun mpfrfloat->rational
(f)
1793 "Convert a raw MPFRFLOAT F into a CL:RATIONAL."
1794 (with-alien ((q (struct sb-gmp
::gmprat
)))
1795 (sb-gmp::__gmpq_init
(addr q
))
1796 (mpfr_get_q (addr q
) f
)
1797 (prog1 (sb-gmp::mpq-
>rational q
)
1798 (sb-gmp::__gmpq_clear
(addr q
)))))
1800 (defun coerce (x type
&optional
(round *mpfr-rnd
*))
1802 ((typep x
'mpfr-float
)
1803 (let ((x-ref (mpfr-float-ref x
)))
1806 (mpfr_get_flt x-ref round
))
1808 (mpfr_get_d x-ref round
))
1810 ;; this will always be exact
1811 (mpfrfloat->rational x-ref
))
1813 (let ((result (make-mpfr-float)))
1814 (mpfr_set (mpfr-float-ref result
) x-ref round
)
1818 (error "Cannot coerce ~s to ~s. Argument must be an actual number."
1821 ((mpfr_fits_slong_p x-ref round
)
1822 (mpfr_get_si x-ref round
))
1823 ((mpfr_fits_ulong_p x-ref round
)
1824 (mpfr_get_ui x-ref round
))
1826 (sb-gmp::with-gmp-mpz-results
(rop)
1827 (mpfr_get_z (addr rop
) x-ref round
)))))
1829 (error "TYPE must be one of SINGLE-FLOAT, DOUBLE-FLOAT or INTEGER.")))))
1830 ((eql type
'mpfr-float
)
1831 (let ((result (make-mpfr-float)))
1834 (mpfr_set_si (mpfr-float-ref result
) x round
))
1836 (mpfr_set_ui (mpfr-float-ref result
) x round
))
1838 (sb-gmp::with-mpz-vars
((x gx
))
1839 (mpfr_set_z (mpfr-float-ref result
) (addr gx
) round
)))
1841 (mpfr_set_flt (mpfr-float-ref result
) x round
))
1843 (mpfr_set_d (mpfr-float-ref result
) x round
))
1845 (sb-gmp::with-mpq-var
(x qx
)
1846 (mpfr_set_q (mpfr-float-ref result
) (addr qx
) round
))))
1849 (error "Unable to handle the combination of ~S and ~S." x type
))))