1d59437c0Smrg /* mpfr_log2 -- log base 2
2d59437c0Smrg
3ba125506Smrg Copyright 2001-2023 Free Software Foundation, Inc.
4efdec83bSmrg Contributed by the AriC and Caramba projects, INRIA.
5d59437c0Smrg
6d59437c0Smrg This file is part of the GNU MPFR Library.
7d59437c0Smrg
8d59437c0Smrg The GNU MPFR Library is free software; you can redistribute it and/or modify
9d59437c0Smrg it under the terms of the GNU Lesser General Public License as published by
10d59437c0Smrg the Free Software Foundation; either version 3 of the License, or (at your
11d59437c0Smrg option) any later version.
12d59437c0Smrg
13d59437c0Smrg The GNU MPFR Library is distributed in the hope that it will be useful, but
14d59437c0Smrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15d59437c0Smrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16d59437c0Smrg License for more details.
17d59437c0Smrg
18d59437c0Smrg You should have received a copy of the GNU Lesser General Public License
19d59437c0Smrg along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
202ba2404bSmrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21d59437c0Smrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22d59437c0Smrg
23d59437c0Smrg #define MPFR_NEED_LONGLONG_H
24d59437c0Smrg #include "mpfr-impl.h"
25d59437c0Smrg
26d59437c0Smrg /* The computation of r=log2(a)
27d59437c0Smrg r=log2(a)=log(a)/log(2) */
28d59437c0Smrg
29d59437c0Smrg int
mpfr_log2(mpfr_ptr r,mpfr_srcptr a,mpfr_rnd_t rnd_mode)30d59437c0Smrg mpfr_log2 (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode)
31d59437c0Smrg {
32d59437c0Smrg int inexact;
33d59437c0Smrg MPFR_SAVE_EXPO_DECL (expo);
34d59437c0Smrg
35d59437c0Smrg MPFR_LOG_FUNC
36*ec6772edSmrg (("a[%Pd]=%.*Rg rnd=%d", mpfr_get_prec (a), mpfr_log_prec, a, rnd_mode),
37*ec6772edSmrg ("r[%Pd]=%.*Rg inexact=%d", mpfr_get_prec (r), mpfr_log_prec, r,
38d59437c0Smrg inexact));
39d59437c0Smrg
40d59437c0Smrg if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a)))
41d59437c0Smrg {
42d59437c0Smrg /* If a is NaN, the result is NaN */
43d59437c0Smrg if (MPFR_IS_NAN (a))
44d59437c0Smrg {
45d59437c0Smrg MPFR_SET_NAN (r);
46d59437c0Smrg MPFR_RET_NAN;
47d59437c0Smrg }
48d59437c0Smrg /* check for infinity before zero */
49d59437c0Smrg else if (MPFR_IS_INF (a))
50d59437c0Smrg {
51d59437c0Smrg if (MPFR_IS_NEG (a))
52d59437c0Smrg /* log(-Inf) = NaN */
53d59437c0Smrg {
54d59437c0Smrg MPFR_SET_NAN (r);
55d59437c0Smrg MPFR_RET_NAN;
56d59437c0Smrg }
57d59437c0Smrg else /* log(+Inf) = +Inf */
58d59437c0Smrg {
59d59437c0Smrg MPFR_SET_INF (r);
60d59437c0Smrg MPFR_SET_POS (r);
61d59437c0Smrg MPFR_RET (0);
62d59437c0Smrg }
63d59437c0Smrg }
64d59437c0Smrg else /* a is zero */
65d59437c0Smrg {
66d59437c0Smrg MPFR_ASSERTD (MPFR_IS_ZERO (a));
67d59437c0Smrg MPFR_SET_INF (r);
68d59437c0Smrg MPFR_SET_NEG (r);
69299c6f0cSmrg MPFR_SET_DIVBY0 ();
70d59437c0Smrg MPFR_RET (0); /* log2(0) is an exact -infinity */
71d59437c0Smrg }
72d59437c0Smrg }
73d59437c0Smrg
74d59437c0Smrg /* If a is negative, the result is NaN */
75d59437c0Smrg if (MPFR_UNLIKELY (MPFR_IS_NEG (a)))
76d59437c0Smrg {
77d59437c0Smrg MPFR_SET_NAN (r);
78d59437c0Smrg MPFR_RET_NAN;
79d59437c0Smrg }
80d59437c0Smrg
81d59437c0Smrg /* If a is 1, the result is 0 */
82d59437c0Smrg if (MPFR_UNLIKELY (mpfr_cmp_ui (a, 1) == 0))
83d59437c0Smrg {
84d59437c0Smrg MPFR_SET_ZERO (r);
85d59437c0Smrg MPFR_SET_POS (r);
86d59437c0Smrg MPFR_RET (0); /* only "normal" case where the result is exact */
87d59437c0Smrg }
88d59437c0Smrg
89d59437c0Smrg /* If a is 2^N, log2(a) is exact*/
90d59437c0Smrg if (MPFR_UNLIKELY (mpfr_cmp_ui_2exp (a, 1, MPFR_GET_EXP (a) - 1) == 0))
91d59437c0Smrg return mpfr_set_si(r, MPFR_GET_EXP (a) - 1, rnd_mode);
92d59437c0Smrg
93d59437c0Smrg MPFR_SAVE_EXPO_MARK (expo);
94d59437c0Smrg
95d59437c0Smrg /* General case */
96d59437c0Smrg {
97d59437c0Smrg /* Declaration of the intermediary variable */
98d59437c0Smrg mpfr_t t, tt;
99d59437c0Smrg /* Declaration of the size variable */
100d59437c0Smrg mpfr_prec_t Ny = MPFR_PREC(r); /* target precision */
101d59437c0Smrg mpfr_prec_t Nt; /* working precision */
102d59437c0Smrg mpfr_exp_t err; /* error */
103d59437c0Smrg MPFR_ZIV_DECL (loop);
104d59437c0Smrg
105d59437c0Smrg /* compute the precision of intermediary variable */
106d59437c0Smrg /* the optimal number of bits : see algorithms.tex */
107d59437c0Smrg Nt = Ny + 3 + MPFR_INT_CEIL_LOG2 (Ny);
108d59437c0Smrg
109299c6f0cSmrg /* initialize of intermediary variable */
110d59437c0Smrg mpfr_init2 (t, Nt);
111d59437c0Smrg mpfr_init2 (tt, Nt);
112d59437c0Smrg
113d59437c0Smrg /* First computation of log2 */
114d59437c0Smrg MPFR_ZIV_INIT (loop, Nt);
115d59437c0Smrg for (;;)
116d59437c0Smrg {
117d59437c0Smrg /* compute log2 */
118d59437c0Smrg mpfr_const_log2(t,MPFR_RNDD); /* log(2) */
119d59437c0Smrg mpfr_log(tt,a,MPFR_RNDN); /* log(a) */
120d59437c0Smrg mpfr_div(t,tt,t,MPFR_RNDN); /* log(a)/log(2) */
121d59437c0Smrg
122d59437c0Smrg /* estimation of the error */
123d59437c0Smrg err = Nt-3;
124d59437c0Smrg if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
125d59437c0Smrg break;
126d59437c0Smrg
127299c6f0cSmrg /* actualization of the precision */
128d59437c0Smrg MPFR_ZIV_NEXT (loop, Nt);
129d59437c0Smrg mpfr_set_prec (t, Nt);
130d59437c0Smrg mpfr_set_prec (tt, Nt);
131d59437c0Smrg }
132d59437c0Smrg MPFR_ZIV_FREE (loop);
133d59437c0Smrg
134d59437c0Smrg inexact = mpfr_set (r, t, rnd_mode);
135d59437c0Smrg
136d59437c0Smrg mpfr_clear (t);
137d59437c0Smrg mpfr_clear (tt);
138d59437c0Smrg }
139d59437c0Smrg
140d59437c0Smrg MPFR_SAVE_EXPO_FREE (expo);
141d59437c0Smrg return mpfr_check_range (r, inexact, rnd_mode);
142d59437c0Smrg }
143