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
)
187 (defvar +mpfr-precision
+)
188 (defvar *mpfr-version
* nil
)
189 (defvar *mpfr-features
* nil
)
191 (defun try-load-shared-object (pathname)
193 (load-shared-object pathname
:dont-save t
)
198 (or (some #'try-load-shared-object
199 #-
(or win32 darwin
) '("libmpfr.so" "libmpfr.so.4")
200 #+darwin
'("libmpfr.dylib" "libmpfr.4.dylib")
201 #+win32
'("mpfr.dll"))
202 (warn "MPFR not loaded.")))
204 (defun load-mpfr (&key
(persistently t
))
205 (setf *mpfr-version
* nil
207 *features
* (set-difference *features
* '(:sb-mpfr
)))
209 (pushnew 'load-mpfr sb-ext
:*init-hooks
*)
210 ;(pushnew 'uninstall-mpfr-funs sb-ext:*save-hooks*)
212 (let ((success (%load-mpfr
)))
215 (alien-funcall (extern-alien "mpfr_get_version"
216 (function c-string
)))))
217 (cond ((null *mpfr-version
*))
218 ((string<= *mpfr-version
* "3.1")
219 (warn "SB-MPFR requires at least MPFR version 3.1")
222 (setf +mpfr-precision
+
223 (alien-funcall (extern-alien "mpfr_get_default_prec"
225 (pushnew :sb-mpfr
*mpfr-features
*)
226 (setf *features
* (union *features
* *mpfr-features
*))))
231 ;;; types and initialization
233 (define-alien-type nil
238 (mpfr_d (* gmp-limb
))))
240 (define-alien-type mpfr_rnd_enum
250 (declaim (inline mpfr_init2
262 mpfr_set_default_prec
265 (define-alien-routine mpfr_init2 void
266 (x (* (struct mpfrfloat
)))
269 (define-alien-routine mpfr_clear void
270 (x (* (struct mpfrfloat
))))
272 ;;; conversion functions
274 (define-alien-routine mpfr_set void
275 (x (* (struct mpfrfloat
)))
276 (op (* (struct mpfrfloat
)))
279 (define-alien-routine mpfr_set_ui void
280 (x (* (struct mpfrfloat
)))
284 (define-alien-routine mpfr_set_si void
285 (x (* (struct mpfrfloat
)))
289 (define-alien-routine mpfr_set_flt void
290 (x (* (struct mpfrfloat
)))
294 (define-alien-routine mpfr_set_d void
295 (x (* (struct mpfrfloat
)))
299 (define-alien-routine mpfr_set_z void
300 (x (* (struct mpfrfloat
)))
301 (op (* (struct sb-gmp
::gmpint
)))
304 (define-alien-routine mpfr_set_q void
305 (x (* (struct mpfrfloat
)))
306 (op (* (struct sb-gmp
::gmprat
)))
309 (define-alien-routine mpfr_set_nan void
310 (x (* (struct mpfrfloat
))))
312 (define-alien-routine mpfr_set_inf void
313 (x (* (struct mpfrfloat
)))
316 (define-alien-routine mpfr_set_zero void
317 (x (* (struct mpfrfloat
)))
320 (define-alien-routine mpfr_set_default_prec void
323 (define-alien-routine mpfr_get_str
(* char
)
328 (x (* (struct mpfrfloat
)))
331 ;;; conversion functions
333 (declaim (inline mpfr_get_flt
341 (define-alien-routine mpfr_get_flt float
342 (op (* (struct mpfrfloat
)))
345 (define-alien-routine mpfr_get_d double
346 (op (* (struct mpfrfloat
)))
349 (define-alien-routine mpfr_get_si long
350 (op (* (struct mpfrfloat
)))
353 (define-alien-routine mpfr_get_ui unsigned-long
354 (op (* (struct mpfrfloat
)))
357 (define-alien-routine mpfr_get_z int
358 (res (* (struct sb-gmp
::gmpint
)))
359 (op (* (struct mpfrfloat
)))
362 (define-alien-routine mpfr_free_str void
365 (define-alien-routine mpfr_set_str int
366 (x (* (struct mpfrfloat
)))
371 ;;; arithmetic functions
373 (declaim (inline mpfr_add
423 (define-alien-routine mpfr_add int
424 (r (* (struct mpfrfloat
)))
425 (op1 (* (struct mpfrfloat
)))
426 (op2 (* (struct mpfrfloat
)))
429 (define-alien-routine mpfr_add_ui int
430 (r (* (struct mpfrfloat
)))
431 (op1 (* (struct mpfrfloat
)))
435 (define-alien-routine mpfr_add_si int
436 (r (* (struct mpfrfloat
)))
437 (op1 (* (struct mpfrfloat
)))
441 (define-alien-routine mpfr_add_d int
442 (r (* (struct mpfrfloat
)))
443 (op1 (* (struct mpfrfloat
)))
447 (define-alien-routine mpfr_add_z int
448 (r (* (struct mpfrfloat
)))
449 (op1 (* (struct mpfrfloat
)))
450 (op2 (* (struct sb-gmp
::gmpint
)))
453 (define-alien-routine mpfr_add_q int
454 (r (* (struct mpfrfloat
)))
455 (op1 (* (struct mpfrfloat
)))
456 (op2 (* (struct sb-gmp
::gmprat
)))
459 (define-alien-routine mpfr_sub int
460 (r (* (struct mpfrfloat
)))
461 (op1 (* (struct mpfrfloat
)))
462 (op2 (* (struct mpfrfloat
)))
465 (define-alien-routine mpfr_ui_sub int
466 (r (* (struct mpfrfloat
)))
468 (op2 (* (struct mpfrfloat
)))
471 (define-alien-routine mpfr_sub_ui int
472 (r (* (struct mpfrfloat
)))
473 (op1 (* (struct mpfrfloat
)))
477 (define-alien-routine mpfr_si_sub int
478 (r (* (struct mpfrfloat
)))
480 (op2 (* (struct mpfrfloat
)))
483 (define-alien-routine mpfr_sub_si int
484 (r (* (struct mpfrfloat
)))
485 (op1 (* (struct mpfrfloat
)))
489 (define-alien-routine mpfr_d_sub int
490 (r (* (struct mpfrfloat
)))
492 (op2 (* (struct mpfrfloat
)))
495 (define-alien-routine mpfr_sub_d int
496 (r (* (struct mpfrfloat
)))
497 (op1 (* (struct mpfrfloat
)))
501 (define-alien-routine mpfr_z_sub int
502 (r (* (struct mpfrfloat
)))
503 (op1 (* (struct sb-gmp
::gmpint
)))
504 (op2 (* (struct mpfrfloat
)))
507 (define-alien-routine mpfr_sub_z int
508 (r (* (struct mpfrfloat
)))
509 (op1 (* (struct mpfrfloat
)))
510 (op2 (* (struct sb-gmp
::gmpint
)))
513 (define-alien-routine mpfr_sub_q int
514 (r (* (struct mpfrfloat
)))
515 (op1 (* (struct mpfrfloat
)))
516 (op2 (* (struct sb-gmp
::gmprat
)))
519 (define-alien-routine mpfr_mul int
520 (r (* (struct mpfrfloat
)))
521 (op1 (* (struct mpfrfloat
)))
522 (op2 (* (struct mpfrfloat
)))
525 (define-alien-routine mpfr_mul_ui int
526 (r (* (struct mpfrfloat
)))
527 (op1 (* (struct mpfrfloat
)))
531 (define-alien-routine mpfr_mul_si int
532 (r (* (struct mpfrfloat
)))
533 (op1 (* (struct mpfrfloat
)))
537 (define-alien-routine mpfr_mul_d int
538 (r (* (struct mpfrfloat
)))
539 (op1 (* (struct mpfrfloat
)))
543 (define-alien-routine mpfr_mul_z int
544 (r (* (struct mpfrfloat
)))
545 (op1 (* (struct mpfrfloat
)))
546 (op2 (* (struct sb-gmp
::gmpint
)))
549 (define-alien-routine mpfr_mul_q int
550 (r (* (struct mpfrfloat
)))
551 (op1 (* (struct mpfrfloat
)))
552 (op2 (* (struct sb-gmp
::gmprat
)))
555 (define-alien-routine mpfr_sqr int
556 (r (* (struct mpfrfloat
)))
557 (op (* (struct mpfrfloat
)))
560 (define-alien-routine mpfr_div int
561 (r (* (struct mpfrfloat
)))
562 (op1 (* (struct mpfrfloat
)))
563 (op2 (* (struct mpfrfloat
)))
566 (define-alien-routine mpfr_ui_div int
567 (r (* (struct mpfrfloat
)))
569 (op2 (* (struct mpfrfloat
)))
572 (define-alien-routine mpfr_div_ui int
573 (r (* (struct mpfrfloat
)))
574 (op1 (* (struct mpfrfloat
)))
578 (define-alien-routine mpfr_si_div int
579 (r (* (struct mpfrfloat
)))
581 (op2 (* (struct mpfrfloat
)))
584 (define-alien-routine mpfr_div_si int
585 (r (* (struct mpfrfloat
)))
586 (op1 (* (struct mpfrfloat
)))
590 (define-alien-routine mpfr_d_div int
591 (r (* (struct mpfrfloat
)))
593 (op2 (* (struct mpfrfloat
)))
596 (define-alien-routine mpfr_div_d int
597 (r (* (struct mpfrfloat
)))
598 (op1 (* (struct mpfrfloat
)))
602 (define-alien-routine mpfr_div_z int
603 (r (* (struct mpfrfloat
)))
604 (op1 (* (struct mpfrfloat
)))
605 (op2 (* (struct sb-gmp
::gmpint
)))
608 (define-alien-routine mpfr_div_q int
609 (r (* (struct mpfrfloat
)))
610 (op1 (* (struct mpfrfloat
)))
611 (op2 (* (struct sb-gmp
::gmprat
)))
614 (define-alien-routine mpfr_sqrt int
615 (r (* (struct mpfrfloat
)))
616 (op (* (struct mpfrfloat
)))
619 (define-alien-routine mpfr_sqrt_ui int
620 (r (* (struct mpfrfloat
)))
624 (define-alien-routine mpfr_rec_sqrt int
625 (r (* (struct mpfrfloat
)))
626 (op (* (struct mpfrfloat
)))
629 (define-alien-routine mpfr_cbrt int
630 (r (* (struct mpfrfloat
)))
631 (op (* (struct mpfrfloat
)))
634 (define-alien-routine mpfr_root int
635 (r (* (struct mpfrfloat
)))
636 (op (* (struct mpfrfloat
)))
640 (define-alien-routine mpfr_pow int
641 (r (* (struct mpfrfloat
)))
642 (op1 (* (struct mpfrfloat
)))
643 (op2 (* (struct mpfrfloat
)))
646 (define-alien-routine mpfr_pow_ui int
647 (r (* (struct mpfrfloat
)))
648 (op1 (* (struct mpfrfloat
)))
652 (define-alien-routine mpfr_pow_si int
653 (r (* (struct mpfrfloat
)))
654 (op1 (* (struct mpfrfloat
)))
658 (define-alien-routine mpfr_pow_z int
659 (r (* (struct mpfrfloat
)))
660 (op1 (* (struct mpfrfloat
)))
661 (op2 (* (struct sb-gmp
::gmpint
)))
664 (define-alien-routine mpfr_ui_pow int
665 (r (* (struct mpfrfloat
)))
667 (op2 (* (struct mpfrfloat
)))
670 (define-alien-routine mpfr_neg int
671 (r (* (struct mpfrfloat
)))
672 (op (* (struct mpfrfloat
)))
675 (define-alien-routine mpfr_abs int
676 (r (* (struct mpfrfloat
)))
677 (op (* (struct mpfrfloat
)))
680 (define-alien-routine mpfr_dim int
681 (r (* (struct mpfrfloat
)))
682 (op1 (* (struct mpfrfloat
)))
683 (op2 (* (struct mpfrfloat
)))
686 (define-alien-routine mpfr_mul_2ui int
687 (r (* (struct mpfrfloat
)))
688 (op1 (* (struct mpfrfloat
)))
692 (define-alien-routine mpfr_mul_2si int
693 (r (* (struct mpfrfloat
)))
694 (op1 (* (struct mpfrfloat
)))
698 (define-alien-routine mpfr_div_2ui int
699 (r (* (struct mpfrfloat
)))
700 (op1 (* (struct mpfrfloat
)))
704 (define-alien-routine mpfr_div_2si int
705 (r (* (struct mpfrfloat
)))
706 (op1 (* (struct mpfrfloat
)))
710 ;;; special functions
712 (defmacro define-onearg-mpfr-int
(funs)
713 (loop for i in funs collect
`(define-alien-routine ,i int
714 (r (* (struct mpfrfloat
)))
715 (op (* (struct mpfrfloat
)))
718 finally
(return `(progn
719 (declaim (inline ,@funs
))
722 (define-onearg-mpfr-int
763 (defmacro define-twoarg-mpfr-int
(funs)
764 (loop for i in funs collect
`(define-alien-routine ,i int
765 (r (* (struct mpfrfloat
)))
766 (op1 (* (struct mpfrfloat
)))
767 (op2 (* (struct mpfrfloat
)))
770 finally
(return `(progn
771 (declaim (inline ,@funs
))
774 (define-twoarg-mpfr-int
781 (declaim (inline mpfr_fac_ui
788 (define-alien-routine mpfr_fac_ui int
789 (r (* (struct mpfrfloat
)))
793 (define-alien-routine mpfr_zeta_ui int
794 (r (* (struct mpfrfloat
)))
798 (define-alien-routine mpfr_jn int
799 (r (* (struct mpfrfloat
)))
801 (op (* (struct mpfrfloat
)))
804 (define-alien-routine mpfr_yn int
805 (r (* (struct mpfrfloat
)))
807 (op (* (struct mpfrfloat
)))
810 (define-alien-routine mpfr_fma int
811 (r (* (struct mpfrfloat
)))
812 (op1 (* (struct mpfrfloat
)))
813 (op2 (* (struct mpfrfloat
)))
814 (op3 (* (struct mpfrfloat
)))
817 (define-alien-routine mpfr_fms int
818 (r (* (struct mpfrfloat
)))
819 (op1 (* (struct mpfrfloat
)))
820 (op2 (* (struct mpfrfloat
)))
821 (op3 (* (struct mpfrfloat
)))
825 ;;; constant initialization
827 (defmacro define-const-mpfr-int
(funs)
828 (loop for i in funs collect
`(define-alien-routine ,i int
829 (r (* (struct mpfrfloat
)))
832 finally
(return `(progn
833 (declaim (inline ,@funs
))
836 (define-const-mpfr-int
842 (declaim (inline mpfr_sum
))
843 (define-alien-routine mpfr_sum int
844 (r (* (struct mpfrfloat
)))
845 (tab (* (* (struct mpfrfloat
))))
850 ;;; comparison functions
852 (declaim (inline mpfr_cmp
862 (define-alien-routine mpfr_cmp int
863 (op1 (* (struct mpfrfloat
)))
864 (op2 (* (struct mpfrfloat
))))
866 (define-alien-routine mpfr_cmp_ui int
867 (op1 (* (struct mpfrfloat
)))
870 (define-alien-routine mpfr_cmp_si int
871 (op1 (* (struct mpfrfloat
)))
874 (define-alien-routine mpfr_cmp_d int
875 (op1 (* (struct mpfrfloat
)))
878 (define-alien-routine mpfr_cmp_z int
879 (op1 (* (struct mpfrfloat
)))
880 (op2 (* (struct sb-gmp
::gmpint
))))
882 (define-alien-routine mpfr_cmp_q int
883 (op1 (* (struct mpfrfloat
)))
884 (op2 (* (struct sb-gmp
::gmprat
))))
886 (define-alien-routine mpfr_cmp_ui_2exp int
887 (op1 (* (struct mpfrfloat
)))
891 (define-alien-routine mpfr_cmp_si_2exp int
892 (op1 (* (struct mpfrfloat
)))
896 (define-alien-routine mpfr_cmpabs int
897 (op1 (* (struct mpfrfloat
)))
898 (op2 (* (struct mpfrfloat
))))
901 (defmacro define-onearg-mpfr-bool
(funs)
902 (loop for i in funs collect
`(define-alien-routine ,i boolean
903 (op (* (struct mpfrfloat
))))
905 finally
(return `(progn
906 (declaim (inline ,@funs
))
909 (define-onearg-mpfr-bool
917 (declaim (inline mpfr_sgn
))
918 (define-alien-routine mpfr_sgn int
919 (op (* (struct mpfrfloat
))))
921 (defmacro define-twoarg-mpfr-bool
(funs)
922 (loop for i in funs collect
`(define-alien-routine ,i boolean
923 (op1 (* (struct mpfrfloat
)))
924 (op2 (* (struct mpfrfloat
))))
926 finally
(return `(progn
927 (declaim (inline ,@funs
))
930 (define-twoarg-mpfr-bool
940 ;;; miscellaneous functions
942 (defmacro define-mpfr-void
(funs)
943 (loop for i in funs collect
`(define-alien-routine ,i void
)
945 finally
(return `(progn
946 (declaim (inline ,@funs
))
950 (mpfr_clear_underflow
955 mpfr_clear_erangeflag
964 (defmacro define-mpfr-bool
(funs)
965 (loop for i in funs collect
`(define-alien-routine ,i boolean
)
967 finally
(return `(progn
968 (declaim (inline ,@funs
))
980 (declaim (inline mpfr_urandomb
983 (define-alien-routine mpfr_urandomb int
984 (op (* (struct mpfrfloat
)))
985 (s (* (struct sb-gmp
::gmprandstate
))))
987 (define-alien-routine mpfr_urandom int
988 (op (* (struct mpfrfloat
)))
989 (s (* (struct sb-gmp
::gmprandstate
)))
993 ;;; integer and remainder related functions / rounding
995 (define-onearg-mpfr-int
1003 (declaim (inline mpfr_ceil
1012 (define-alien-routine mpfr_ceil int
1013 (r (* (struct mpfrfloat
)))
1014 (op (* (struct mpfrfloat
))))
1016 (define-alien-routine mpfr_floor int
1017 (r (* (struct mpfrfloat
)))
1018 (op (* (struct mpfrfloat
))))
1020 (define-alien-routine mpfr_round int
1021 (r (* (struct mpfrfloat
)))
1022 (op (* (struct mpfrfloat
))))
1024 (define-alien-routine mpfr_trunc int
1025 (r (* (struct mpfrfloat
)))
1026 (op (* (struct mpfrfloat
))))
1028 (define-alien-routine mpfr_modf int
1029 (ir (* (struct mpfrfloat
)))
1030 (fr (* (struct mpfrfloat
)))
1031 (op (* (struct mpfrfloat
)))
1032 (rnd mpfr_rnd_enum
))
1034 (define-alien-routine mpfr_fmod int
1035 (r (* (struct mpfrfloat
)))
1036 (x (* (struct mpfrfloat
)))
1037 (y (* (struct mpfrfloat
)))
1038 (rnd mpfr_rnd_enum
))
1040 (define-alien-routine mpfr_remainder int
1041 (r (* (struct mpfrfloat
)))
1042 (x (* (struct mpfrfloat
)))
1043 (y (* (struct mpfrfloat
)))
1044 (rnd mpfr_rnd_enum
))
1046 (define-alien-routine mpfr_remquo int
1047 (r (* (struct mpfrfloat
)))
1049 (x (* (struct mpfrfloat
)))
1050 (y (* (struct mpfrfloat
)))
1051 (rnd mpfr_rnd_enum
))
1056 (defparameter *mpfr-rnd
* :mpfr_rndn
)
1057 (defparameter *mpfr-base
* 10)
1059 (declaim (inline mpfr-float-ref
1062 (defstruct (mpfr-float (:constructor %make-mpfr-float
))
1063 (ref (make-alien (struct mpfrfloat
))
1064 :type
(alien (* (struct mpfrfloat
))) :read-only t
))
1066 (defun make-mpfr-float (&optional
(precision +mpfr-precision
+))
1067 (declare (optimize (speed 3) (space 3)))
1068 (let* ((float (%make-mpfr-float
))
1069 (ref (mpfr-float-ref float
)))
1070 (mpfr_init2 ref precision
)
1071 (sb-ext:finalize float
(lambda ()
1072 (declare (optimize (speed 3) (space 3) (safety 0)))
1077 (defmacro with-precision
(value &body body
)
1078 `(let* ((old +mpfr-precision
+)
1079 (+mpfr-precision
+ ,value
))
1082 (mpfr_set_default_prec ,value
)
1084 (mpfr_set_default_prec old
))))
1086 (defun set-precision (value)
1087 (check-type value ui
)
1088 (mpfr_set_default_prec value
)
1089 (setf +mpfr-precision
+ value
))
1091 ;;; printing and reader syntax
1093 (defmethod print-object ((obj mpfr-float
) stream
)
1094 (multiple-value-bind (str exp sign
)
1095 (mpfr-float-to-string obj
)
1096 (declare (type (integer -
1 1) sign
))
1097 (if *print-readably
*
1099 (format stream
"#M~s" str
)
1101 (0 (format stream
"#M\"0\""))
1102 (1 (format stream
"#M\"~a@~s\"" str
1103 (- exp
(length str
))))
1104 (-1 (format stream
"#M\"~a@~s\"" str
1105 (- (1+ exp
) (length str
))))))
1107 (format stream
"~a" str
)
1109 (0 (format stream
"0"))
1110 (1 (format stream
".~ae+~s" str exp
))
1111 (-1 (format stream
"-.~ae+~s" (subseq str
1) exp
)))))))
1113 (defun mpfr-float-to-string (x &optional
(rnd *mpfr-rnd
*))
1114 (let ((xr (mpfr-float-ref x
)))
1115 (with-alien ((exp long
)
1118 (setf str
(mpfr_get_str NIL
(addr exp
) *print-base
* 0 xr rnd
))
1119 (multiple-value-prog1
1120 (values (cast str c-string
) exp
(mpfr_cmp_ui xr
0))
1121 (mpfr_free_str str
)))))
1123 (defun mpfr-reader (stream subchar arg
)
1124 (declare (ignore subchar arg
))
1125 (let ((mpfr (make-mpfr-float)))
1126 (mpfr_set_str (mpfr-float-ref mpfr
)
1127 (read stream t nil t
)
1128 *mpfr-base
* *mpfr-rnd
*)
1131 (defun enable-mpfr-syntax (readtable)
1132 (set-dispatch-macro-character #\
# #\M
#'mpfr-reader readtable
))
1133 (enable-mpfr-syntax *readtable
*)
1136 ;;; arithmetic functions
1138 (defun add (x y
&optional
(round *mpfr-rnd
*))
1139 (if (typep x
'mpfr-float
)
1140 (let* ((res (make-mpfr-float))
1141 (r (mpfr-float-ref res
))
1142 (xr (mpfr-float-ref x
))
1145 (mpfr_add r xr
(mpfr-float-ref y
) round
))
1147 (mpfr_add_ui r xr y round
))
1149 (mpfr_add_si r xr y round
))
1151 (mpfr_add_d r xr y round
))
1153 (sb-gmp::with-mpz-vars
((y gy
))
1154 (mpfr_add_z r xr
(addr gy
) round
)))
1156 (sb-gmp::with-mpq-var
(y qy
)
1157 (mpfr_add_q r xr
(addr qy
) round
))))))
1163 (defun sub (x y
&optional
(round *mpfr-rnd
*))
1164 (let* ((res (make-mpfr-float))
1165 (r (mpfr-float-ref res
))
1168 (let ((xr (mpfr-float-ref x
)))
1171 (mpfr_sub r xr
(mpfr-float-ref y
) round
))
1173 (mpfr_sub_ui r xr y round
))
1175 (mpfr_sub_si r xr y round
))
1177 (mpfr_sub_d r xr y round
))
1179 (sb-gmp::with-mpz-vars
((y gy
))
1180 (mpfr_sub_z r xr
(addr gy
) round
)))
1182 (sb-gmp::with-mpq-var
(y qy
)
1183 (mpfr_sub_q r xr
(addr qy
) round
))))))
1187 (mpfr_ui_sub r x
(mpfr-float-ref y
) round
))))
1191 (mpfr_si_sub r x
(mpfr-float-ref y
) round
))))
1195 (mpfr_d_sub r x
(mpfr-float-ref y
) round
))))
1199 (sb-gmp::with-mpz-vars
((x gx
))
1200 (mpfr_z_sub r
(addr gx
) (mpfr-float-ref y
) round
))))))))
1203 (defun mul (x y
&optional
(round *mpfr-rnd
*))
1204 (if (typep x
'mpfr-float
)
1205 (let* ((res (make-mpfr-float))
1206 (r (mpfr-float-ref res
))
1207 (xr (mpfr-float-ref x
))
1210 (mpfr_mul r xr
(mpfr-float-ref y
) round
))
1212 (mpfr_mul_ui r xr y round
))
1214 (mpfr_mul_si r xr y round
))
1216 (mpfr_mul_d r xr y round
))
1218 (sb-gmp::with-mpz-vars
((y gy
))
1219 (mpfr_mul_z r xr
(addr gy
) round
)))
1221 (sb-gmp::with-mpq-var
(y qy
)
1222 (mpfr_mul_q r xr
(addr qy
) round
))))))
1228 (defun sqare (x &optional
(round *mpfr-rnd
*))
1229 (let ((r (make-mpfr-float)))
1230 (values r
(mpfr_sqr (mpfr-float-ref r
) (mpfr-float-ref x
) round
))))
1232 (defun div (x y
&optional
(round *mpfr-rnd
*))
1233 (let* ((res (make-mpfr-float))
1234 (r (mpfr-float-ref res
))
1237 (let ((xr (mpfr-float-ref x
)))
1240 (mpfr_div r xr
(mpfr-float-ref y
) round
))
1242 (mpfr_div_ui r xr y round
))
1244 (mpfr_div_si r xr y round
))
1246 (mpfr_div_d r xr y round
))
1248 (sb-gmp::with-mpz-vars
((y gy
))
1249 (mpfr_div_z r xr
(addr gy
) round
)))
1251 (sb-gmp::with-mpq-var
(y qy
)
1252 (mpfr_div_q r xr
(addr qy
) round
))))))
1256 (mpfr_ui_div r x
(mpfr-float-ref y
) round
))))
1260 (mpfr_si_div r x
(mpfr-float-ref y
) round
))))
1264 (mpfr_d_div r x
(mpfr-float-ref y
) round
)))))))
1267 (defun sqrt (x &optional
(round *mpfr-rnd
*))
1268 (let* ((res (make-mpfr-float))
1269 (r (mpfr-float-ref res
))
1272 (mpfr_sqrt_ui r x round
))
1274 (mpfr_sqrt r
(mpfr-float-ref x
) round
)))))
1277 (defun reciprocal-sqrt (x &optional
(round *mpfr-rnd
*))
1278 (let* ((res (make-mpfr-float))
1279 (r (mpfr-float-ref res
))
1280 (i (mpfr_rec_sqrt r
(mpfr-float-ref x
) round
)))
1283 (defun cubic-root (x &optional
(round *mpfr-rnd
*))
1284 (let* ((res (make-mpfr-float))
1285 (r (mpfr-float-ref res
))
1286 (i (mpfr_cbrt r
(mpfr-float-ref x
) round
)))
1289 (defun k-root (x k
&optional
(round *mpfr-rnd
*))
1291 (let* ((res (make-mpfr-float))
1292 (r (mpfr-float-ref res
))
1293 (i (mpfr_root r
(mpfr-float-ref x
) k round
)))
1296 (defun power (x y
&optional
(round *mpfr-rnd
*))
1297 (let* ((res (make-mpfr-float))
1298 (r (mpfr-float-ref res
))
1301 (let ((xr (mpfr-float-ref x
)))
1304 (mpfr_pow r xr
(mpfr-float-ref y
) round
))
1306 (mpfr_pow_ui r xr y round
))
1308 (mpfr_pow_si r xr y round
))
1310 (sb-gmp::with-mpz-vars
((y gy
))
1311 (mpfr_pow_z r xr
(addr gy
) round
))))))
1315 (mpfr_ui_pow r x
(mpfr-float-ref y
) round
)))))))
1318 (defun negate (x &optional
(round *mpfr-rnd
*))
1319 (let* ((res (make-mpfr-float))
1320 (r (mpfr-float-ref res
))
1321 (i (mpfr_neg r
(mpfr-float-ref x
) round
)))
1324 (defun abs (x &optional
(round *mpfr-rnd
*))
1325 (let* ((res (make-mpfr-float))
1326 (r (mpfr-float-ref res
))
1327 (i (mpfr_abs r
(mpfr-float-ref x
) round
)))
1330 (defun dim (x y
&optional
(round *mpfr-rnd
*))
1331 (let* ((res (make-mpfr-float))
1332 (r (mpfr-float-ref res
))
1333 (i (mpfr_dim r
(mpfr-float-ref x
) (mpfr-float-ref y
) round
)))
1336 (defun mul-2-raised (x y
&optional
(round *mpfr-rnd
*))
1338 (let* ((res (make-mpfr-float))
1339 (r (mpfr-float-ref res
))
1342 (mpfr_mul_2ui r
(mpfr-float-ref x
) y round
))
1344 (mpfr_mul_2si r
(mpfr-float-ref x
) y round
)))))
1347 (defun div-2-raised (x y
&optional
(round *mpfr-rnd
*))
1349 (let* ((res (make-mpfr-float))
1350 (r (mpfr-float-ref res
))
1353 (mpfr_div_2ui r
(mpfr-float-ref x
) y round
))
1355 (mpfr_div_2si r
(mpfr-float-ref x
) y round
)))))
1358 ;;; special functions
1360 (defmacro define-onearg-mpfr-funs
(funs)
1361 (loop for
(clfun mfun
) in funs
1362 collect
`(defun ,clfun
(x &optional
(round *mpfr-rnd
*))
1363 (let* ((result (make-mpfr-float))
1364 (i (,mfun
(mpfr-float-ref result
)
1369 finally
(return `(progn
1372 (define-onearg-mpfr-funs
1401 (lngamma mpfr_lngamma
)
1402 (digamma mpfr_digamma
)
1411 (defun atan (y &optional x
(round *mpfr-rnd
*))
1413 (let* ((result (make-mpfr-float))
1414 (i (mpfr_atan2 (mpfr-float-ref result
)
1419 (let* ((result (make-mpfr-float))
1420 (i (mpfr_atan (mpfr-float-ref result
)
1423 (values result i
))))
1425 (defun sin-cos (x &optional
(round *mpfr-rnd
*))
1426 (let* ((sin (make-mpfr-float))
1427 (cos (make-mpfr-float))
1428 (i (mpfr_sin_cos (mpfr-float-ref sin
)
1429 (mpfr-float-ref cos
)
1432 (values sin cos i
)))
1434 (defun sinh-cosh (x &optional
(round *mpfr-rnd
*))
1435 (let* ((sin (make-mpfr-float))
1436 (cos (make-mpfr-float))
1437 (i (mpfr_sinh_cosh (mpfr-float-ref sin
)
1438 (mpfr-float-ref cos
)
1441 (values sin cos i
)))
1443 (defun arithmetic-geometric-mean (u v
&optional
(round *mpfr-rnd
*))
1444 (let* ((result (make-mpfr-float))
1445 (i (mpfr_agm (mpfr-float-ref result
)
1451 (defun hypot (x y
&optional
(round *mpfr-rnd
*))
1452 (let* ((result (make-mpfr-float))
1453 (i (mpfr_hypot (mpfr-float-ref result
)
1459 (defun fac (x &optional
(round *mpfr-rnd
*))
1460 (let* ((result (make-mpfr-float))
1461 (i (mpfr_fac_ui (mpfr-float-ref result
)
1466 (defun zeta (x &optional
(round *mpfr-rnd
*))
1467 (let* ((result (make-mpfr-float))
1470 (mpfr_zeta (mpfr-float-ref result
)
1474 (mpfr_zeta_ui (mpfr-float-ref result
)
1479 (defun jn (n x
&optional
(round *mpfr-rnd
*))
1481 (let* ((result (make-mpfr-float))
1482 (i (mpfr_jn (mpfr-float-ref result
)
1488 (defun yn (n x
&optional
(round *mpfr-rnd
*))
1490 (let* ((result (make-mpfr-float))
1491 (i (mpfr_yn (mpfr-float-ref result
)
1497 (defun fma (x y z
&optional
(round *mpfr-rnd
*))
1498 "fma X Y Z = (X * Y) + Z"
1499 (let* ((result (make-mpfr-float))
1500 (i (mpfr_fma (mpfr-float-ref result
)
1507 (defun fms (x y z
&optional
(round *mpfr-rnd
*))
1508 "fma X Y Z = (X * Y) - Z"
1509 (let* ((result (make-mpfr-float))
1510 (i (mpfr_fms (mpfr-float-ref result
)
1517 (defun sum (seq &optional
(round *mpfr-rnd
*))
1518 (let ((length (length seq
))
1520 (declare (type (integer -
1 #.most-positive-fixnum
) idx
))
1521 (let ((result (make-mpfr-float))
1522 (ar (make-alien (* (struct mpfrfloat
)) length
)))
1525 (map nil
(lambda (x)
1526 (setf (deref ar
(incf idx
))
1527 (mpfr-float-ref x
)))
1529 (let ((i (mpfr_sum (mpfr-float-ref result
)
1539 (defmacro define-const-mpfr-funs
(funs)
1540 (loop for
(fname mname
) in funs
1541 collect
`(defun ,fname
(&optional
(round *mpfr-rnd
*))
1542 (let* ((result (make-mpfr-float))
1543 (i (,mname
(mpfr-float-ref result
)
1547 finally
(return `(progn
1550 (define-const-mpfr-funs
1551 ((const-log2 mpfr_const_log2
)
1552 (const-pi mpfr_const_pi
)
1553 (const-euler mpfr_const_euler
)
1554 (const-catalan mpfr_const_catalan
)))
1556 ;;; comparison functions and predicates
1558 (defmacro define-onearg-mpfr-predicates
(funs)
1559 (loop for
(fname mname
) in funs
1560 collect
`(defun ,fname
(x)
1561 (,mname
(mpfr-float-ref x
)))
1563 finally
(return `(progn
1566 (define-onearg-mpfr-predicates
1568 (infinityp mpfr_inf_p
)
1569 (numberp mpfr_number_p
)
1571 (integerp mpfr_integer_p
)
1572 (regularp mpfr_regular_p
)))
1574 (defmacro define-twoarg-mpfr-predicates
(funs)
1575 (loop for
(fname mname
) in funs
1576 collect
`(defun ,fname
(x y
)
1577 (,mname
(mpfr-float-ref x
)
1578 (mpfr-float-ref y
)))
1580 finally
(return `(progn
1583 (define-twoarg-mpfr-predicates
1584 ((compare-abs mpfr_cmpabs
)
1586 (>= mpfr_greaterequal_p
)
1588 (<= mpfr_lessequal_p
)
1590 (/= mpfr_lessgreater_p
)
1591 (unorderedp mpfr_unordered_p
)))
1593 (defun compare (x y
)
1594 (if (typep x
'mpfr-float
)
1597 (mpfr_cmp (mpfr-float-ref x
)
1598 (mpfr-float-ref y
)))
1600 (mpfr_cmp_ui (mpfr-float-ref x
) y
))
1602 (mpfr_cmp_si (mpfr-float-ref x
) y
))
1604 (mpfr_cmp_d (mpfr-float-ref x
) y
))
1606 (sb-gmp::with-mpz-vars
((y gy
))
1607 (mpfr_cmp_z (mpfr-float-ref x
) (addr gy
))))
1609 (sb-gmp::with-mpq-var
(y qy
)
1610 (mpfr_cmp_q (mpfr-float-ref x
) (addr qy
)))))
1615 (defun compare-2exp (x y exp
)
1616 (if (typep x
'mpfr-float
)
1619 (mpfr_cmp_ui_2exp (mpfr-float-ref x
) y exp
))
1621 (mpfr_cmp_si_2exp (mpfr-float-ref x
) y exp
)))
1624 (compare-2exp y x exp
)))))
1627 ;;; miscellaneous functions
1629 (defmacro define-mpfr-flag-funs
(funs)
1630 (loop for
(pname mname
) in funs
1631 collect
`(defun ,pname
()
1632 (declare (optimize (speed 3) (space 3)))
1635 collect pname into names
1636 finally
(return `(progn
1637 (declaim (inline ,@names
))
1640 (define-mpfr-flag-funs
1641 ((clear-underflow mpfr_clear_underflow
)
1642 (clear-overflow mpfr_clear_overflow
)
1643 (clear-div-by-zero mpfr_clear_divby0
)
1644 (clear-nan-flag mpfr_clear_nanflag
)
1645 (clear-inex-flag mpfr_clear_inexflag
)
1646 (clear-erange-flag mpfr_clear_erangeflag
)
1647 (set-underflow-flag mpfr_set_underflow
)
1648 (set-overflow-flag mpfr_set_overflow
)
1649 (set-div-by-zero-flag mpfr_set_divby0
)
1650 (set-nan-flag mpfr_set_nanflag
)
1651 (set-inex-flag mpfr_set_inexflag
)
1652 (set-erange-flag mpfr_set_erangeflag
)
1653 (clear-flags mpfr_clear_flags
)))
1656 (defmacro define-mpfr-flag-predicates
(funs)
1657 (loop for
(pname mname
) in funs
1658 collect
`(defun ,pname
()
1659 (declare (optimize (speed 3) (space 3)))
1662 collect pname into names
1663 finally
(return `(progn
1664 (declaim (inline ,@names
))
1667 (define-mpfr-flag-predicates
1668 ((underflowp mpfr_underflow_p
)
1669 (overflowp mpfr_overflow_p
)
1670 (div-by-zero-p mpfr_divby0_p
)
1671 (nanflag-p mpfr_nanflag_p
)
1672 (inexflag-p mpfr_inexflag_p
)
1673 (erangeflag-p mpfr_erangeflag_p
)))
1676 ;;; random number generation
1678 (defun urandomb (state)
1679 (check-type state sb-gmp
::gmp-rstate
)
1680 (let* ((ref (sb-gmp::gmp-rstate-ref state
))
1681 (result (make-mpfr-float))
1682 (i (mpfr_urandomb (mpfr-float-ref result
)
1686 (defun urandom (state &optional
(round *mpfr-rnd
*))
1687 (check-type state sb-gmp
::gmp-rstate
)
1688 (let* ((ref (sb-gmp::gmp-rstate-ref state
))
1689 (result (make-mpfr-float))
1690 (i (mpfr_urandom (mpfr-float-ref result
)
1696 ;;; integer and remainder related functions / rounding
1698 (define-onearg-mpfr-funs
1699 ((rounded-int mpfr_rint
)
1700 (rounded-int-ceiling mpfr_rint_ceil
)
1701 (rounded-int-floor mpfr_rint_floor
)
1702 (rounded-int-round mpfr_rint_round
)
1703 (rounded-int-truncate mpfr_rint_trunc
)
1704 (fractional mpfr_frac
)))
1706 (defmacro define-onearg-no-rnd-mpfr-funs
(funs)
1707 (loop for
(clfun mfun
) in funs
1708 collect
`(defun ,clfun
(x)
1709 (let* ((result (make-mpfr-float))
1710 (i (,mfun
(mpfr-float-ref result
)
1711 (mpfr-float-ref x
))))
1714 finally
(return `(progn
1717 (define-onearg-no-rnd-mpfr-funs
1721 (truncate mpfr_trunc
)))
1723 (defun modf (x &optional
(round *mpfr-rnd
*))
1724 (let* ((integral (make-mpfr-float))
1725 (fractional (make-mpfr-float))
1726 (i (mpfr_modf (mpfr-float-ref integral
)
1727 (mpfr-float-ref fractional
)
1730 (values integral fractional i
)))
1732 (defun fmod (x y
&optional
(round *mpfr-rnd
*))
1733 (let* ((result (make-mpfr-float))
1734 (i (mpfr_fmod (mpfr-float-ref result
)
1740 (defun remainder (x y
&optional
(round *mpfr-rnd
*))
1741 (let* ((result (make-mpfr-float))
1742 (i (mpfr_remainder (mpfr-float-ref result
)
1748 (defun remainder-quot (x y
&optional
(round *mpfr-rnd
*))
1749 (with-alien ((q long
))
1750 (let* ((result (make-mpfr-float))
1751 (i (mpfr_remquo (mpfr-float-ref result
)
1756 (values result q i
))))
1761 (declaim (inline mpfr_fits_ulong_p mpfr_fits_slong_p
))
1763 (define-alien-routine mpfr_fits_ulong_p boolean
1764 (x (* (struct mpfrfloat
)))
1765 (rnd mpfr_rnd_enum
))
1767 (define-alien-routine mpfr_fits_slong_p boolean
1768 (x (* (struct mpfrfloat
)))
1769 (rnd mpfr_rnd_enum
))
1771 (defun coerce (x type
&optional
(round *mpfr-rnd
*))
1773 ((typep x
'mpfr-float
)
1774 (let ((x-ref (mpfr-float-ref x
)))
1777 (mpfr_get_flt x-ref round
))
1779 (mpfr_get_d x-ref round
))
1781 (let ((result (make-mpfr-float)))
1782 (mpfr_set (mpfr-float-ref result
) x-ref round
)
1786 (error "Cannot coerce ~s to ~s. Argument must be an actual number."
1789 ((mpfr_fits_slong_p x-ref round
)
1790 (mpfr_get_si x-ref round
))
1791 ((mpfr_fits_ulong_p x-ref round
)
1792 (mpfr_get_ui x-ref round
))
1794 (sb-gmp::with-gmp-mpz-results
(rop)
1795 (mpfr_get_z (addr rop
) x-ref round
)))))
1797 (error "TYPE must be one of SINGLE-FLOAT, DOUBLE-FLOAT or INTEGER.")))))
1798 ((eql type
'mpfr-float
)
1799 (let ((result (make-mpfr-float)))
1802 (mpfr_set_si (mpfr-float-ref result
) x round
))
1804 (mpfr_set_ui (mpfr-float-ref result
) x round
))
1806 (sb-gmp::with-mpz-vars
((x gx
))
1807 (mpfr_set_z (mpfr-float-ref result
) (addr gx
) round
)))
1809 (mpfr_set_flt (mpfr-float-ref result
) x round
))
1811 (mpfr_set_d (mpfr-float-ref result
) x round
))
1813 (sb-gmp::with-mpq-var
(x qx
)
1814 (mpfr_set_q (mpfr-float-ref result
) (addr qx
) round
))))
1817 (error "Unable to handle the combination of ~S and ~S." x type
))))