1 /* mpfr_log2p1 -- Compute log2(1+x) 2 3 Copyright 2001-2023 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #define MPFR_NEED_LONGLONG_H /* needed for MPFR_INT_CEIL_LOG2 */ 24 #include "mpfr-impl.h" 25 26 #define ULSIZE (sizeof (unsigned long) * CHAR_BIT) 27 28 /* return non-zero if log2(1+x) is exactly representable in infinite precision, 29 and in such case the returned value is k such that 1+x = 2^k (the case k=0 30 cannot happen since we assume x<>0) */ 31 static mpfr_exp_t 32 mpfr_log2p1_isexact (mpfr_srcptr x) 33 { 34 /* log2(1+x) is exactly representable when 1+x is a power of two, 35 we thus simply compute 1+x with 1-bit precision and check whether 36 the addition is exact. This routine is called with extended exponent 37 range, thus no need to extend it. */ 38 mpfr_t t; 39 int inex; 40 mpfr_exp_t e; 41 42 mpfr_init2 (t, 1); 43 inex = mpfr_add_ui (t, x, 1, MPFR_RNDZ); 44 e = MPFR_GET_EXP (t); 45 mpfr_clear (t); 46 return inex == 0 ? e - 1 : 0; 47 } 48 49 /* in case x=2^k and we can decide of the correct rounding, 50 put the correctly-rounded value in y and return the corresponding 51 ternary value (which is necessarily non-zero), 52 otherwise return 0 */ 53 static int 54 mpfr_log2p1_special (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) 55 { 56 mpfr_exp_t expx = MPFR_GET_EXP(x); 57 mpfr_exp_t k = expx - 1, expk; 58 mpfr_prec_t prec; 59 mpfr_t t; 60 int inex; 61 62 if (k <= 0 || mpfr_cmp_si_2exp (x, 1, k) != 0) 63 return 0; 64 /* k < log2(1+x) < k + 1/x/log(2) < k + 2/x */ 65 expk = MPFR_INT_CEIL_LOG2(k); /* exponent of k */ 66 /* 2/x < 2^(2-EXP(x)) thus if 2-EXP(x) < expk - PREC(y) - 1, 67 we have 2/x < 1/4*ulp(k) and we can decide the correct rounding */ 68 if (2 - expx >= expk - MPFR_PREC(y) - 1) 69 return 0; 70 prec = (MPFR_PREC(y) + 2 <= ULSIZE) ? ULSIZE : MPFR_PREC(y) + 2; 71 mpfr_init2 (t, prec); 72 mpfr_set_ui (t, k, MPFR_RNDZ); /* exact since prec >= ULSIZE */ 73 mpfr_nextabove (t); 74 /* now k < t < k + 2/x and round(t) = round(log2(1+x)) */ 75 inex = mpfr_set (y, t, rnd_mode); 76 mpfr_clear (t); 77 /* Warning: for RNDF, the mpfr_set calls above might return 0 */ 78 return (rnd_mode == MPFR_RNDF) ? 1 : inex; 79 } 80 81 /* The computation of log2p1 is done by log2p1(x) = log1p(x)/log(2) */ 82 int 83 mpfr_log2p1 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) 84 { 85 int comp, inexact, nloop; 86 mpfr_t t, lg2; 87 mpfr_prec_t Ny = MPFR_PREC(y), prec; 88 MPFR_ZIV_DECL (loop); 89 MPFR_SAVE_EXPO_DECL (expo); 90 91 MPFR_LOG_FUNC 92 (("x[%Pd]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode), 93 ("y[%Pd]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y, 94 inexact)); 95 96 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) 97 return mpfr_log1p (y, x, rnd_mode); /* same result for singular cases */ 98 99 comp = mpfr_cmp_si (x, -1); 100 /* log2p1(x) is undefined for x < -1 */ 101 if (MPFR_UNLIKELY(comp <= 0)) 102 { 103 if (comp == 0) 104 /* x=0: log2p1(-1)=-inf (divide-by-zero exception) */ 105 { 106 MPFR_SET_INF (y); 107 MPFR_SET_NEG (y); 108 MPFR_SET_DIVBY0 (); 109 MPFR_RET (0); 110 } 111 MPFR_SET_NAN (y); 112 MPFR_RET_NAN; 113 } 114 115 MPFR_SAVE_EXPO_MARK (expo); 116 117 prec = Ny + MPFR_INT_CEIL_LOG2 (Ny) + 6; 118 119 mpfr_init2 (t, prec); 120 mpfr_init2 (lg2, prec); 121 122 MPFR_ZIV_INIT (loop, prec); 123 for (nloop = 0; ; nloop++) 124 { 125 mpfr_log1p (t, x, MPFR_RNDN); 126 mpfr_const_log2 (lg2, MPFR_RNDN); 127 mpfr_div (t, t, lg2, MPFR_RNDN); 128 /* t = log2(1+x) * (1 + theta)^3 where |theta| < 2^-prec, 129 for prec >= 2 we have |(1 + theta)^3 - 1| < 4*theta. 130 Note: contrary to log10p1, no underflow is possible in extended 131 exponent range, since for tiny x, |log2(1+x)| ~ |x|/log(2) >= |x|, 132 and x is representable, thus x/log(2) too. */ 133 if (MPFR_LIKELY (MPFR_CAN_ROUND (t, prec - 2, Ny, rnd_mode))) 134 break; 135 136 if (nloop == 0) 137 { 138 /* check for exact cases */ 139 mpfr_exp_t k; 140 141 MPFR_LOG_MSG (("check for exact cases\n", 0)); 142 k = mpfr_log2p1_isexact (x); 143 if (k != 0) /* 1+x = 2^k */ 144 { 145 inexact = mpfr_set_si (y, k, rnd_mode); 146 goto end; 147 } 148 149 /* if x = 2^k with huge k, Ziv's loop will fail */ 150 inexact = mpfr_log2p1_special (y, x, rnd_mode); 151 if (inexact != 0) 152 goto end; 153 } 154 155 MPFR_ZIV_NEXT (loop, prec); 156 mpfr_set_prec (t, prec); 157 mpfr_set_prec (lg2, prec); 158 } 159 inexact = mpfr_set (y, t, rnd_mode); 160 161 end: 162 MPFR_ZIV_FREE (loop); 163 mpfr_clear (t); 164 mpfr_clear (lg2); 165 166 MPFR_SAVE_EXPO_FREE (expo); 167 return mpfr_check_range (y, inexact, rnd_mode); 168 } 169