+ bigfr_set_prec(ent_scratch_bigfr,
+ internal_get_precision(precision));
+
+ bfrnumber = Fcoerce_number(number, Qbigfr, Qnil);
+ bigfr_log2(ent_scratch_bigfr, XBIGFR_DATA(bfrnumber));
+ return make_bigfr_bfr(ent_scratch_bigfr);
+#else
+ number = ent_lift(number, FLOAT_T, NULL);
+
+ RETURN_WHEN_INDEF(number);
+
+ if (FLOATP(number)) {
+ fpfloat d;
+#if HAVE_LOG2
+ d = log2(XFLOAT_DATA(number));
+ return make_float(d);
+#elif HAVE_LOG
+ static const fpflot log_2 - log(2);
+ d = log(XFLOAT_DATA(number));
+ RETURN_WHEN_INDEF(d);
+ return make_float(d/log_2);
+#else
+ return ase_unary_operation_undefined(number);
+#endif
+ }
+
+ Fsignal(Qarith_error, list1(number));
+ return Qnil;
+
+ if (NILP(precision));
+#endif /* HAVE_MPFR */
+}
+
+DEFUN("log", Flog, 1, 3, 0, /*
+Return the natural logarithm of NUMBER.
+If second optional argument BASE is given, return the logarithm of
+NUMBER using that base.
+If third optional argument PRECISION is given, use its value
+(an integer) as precision.
+*/
+ (number, base, precision))
+{
+ RETURN_WHEN_INDEF(number);
+
+ if (INTEGERP(base)) {
+ switch(XINT(base)) {
+ case 2 : return Flog2 (number, precision);
+ case 10: return Flog10(number, precision);
+ default: break; /* Intentional Fall through */
+ }
+ }
+
+
+#if defined HAVE_MPFR && defined WITH_MPFR
+ if (!NILP(base)) {
+ /* Not all bignumber libs optimize log2, for instance MPFR
+ implements log2 in function of log. */
+ Lisp_Object _logn, _logb;
+ _logn = Flog(number, Qnil, precision);
+ RETURN_WHEN_INDEF(_logn);
+ _logb = Flog(base, Qnil, precision);
+ return ent_binop(ASE_BINARY_OP_QUO, _logn, _logb);