xref: /netbsd-src/external/lgpl3/mpfr/dist/src/cmp_ui.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1d59437c0Smrg /* mpfr_cmp_ui_2exp -- compare a floating-point number with an unsigned
2d59437c0Smrg machine integer multiplied by a power of 2
3d59437c0Smrg 
4*ba125506Smrg Copyright 1999, 2001-2004, 2006-2023 Free Software Foundation, Inc.
5efdec83bSmrg Contributed by the AriC and Caramba projects, INRIA.
6d59437c0Smrg 
7d59437c0Smrg This file is part of the GNU MPFR Library.
8d59437c0Smrg 
9d59437c0Smrg The GNU MPFR Library is free software; you can redistribute it and/or modify
10d59437c0Smrg it under the terms of the GNU Lesser General Public License as published by
11d59437c0Smrg the Free Software Foundation; either version 3 of the License, or (at your
12d59437c0Smrg option) any later version.
13d59437c0Smrg 
14d59437c0Smrg The GNU MPFR Library is distributed in the hope that it will be useful, but
15d59437c0Smrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16d59437c0Smrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17d59437c0Smrg License for more details.
18d59437c0Smrg 
19d59437c0Smrg You should have received a copy of the GNU Lesser General Public License
20d59437c0Smrg along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
212ba2404bSmrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
22d59437c0Smrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23d59437c0Smrg 
24d59437c0Smrg #define MPFR_NEED_LONGLONG_H
25d59437c0Smrg #include "mpfr-impl.h"
26d59437c0Smrg 
27d59437c0Smrg /* returns a positive value if b > i*2^f,
28d59437c0Smrg            a negative value if b < i*2^f,
29d59437c0Smrg            zero if b = i*2^f.
30d59437c0Smrg    b must not be NaN
31d59437c0Smrg */
32d59437c0Smrg 
33d59437c0Smrg int
mpfr_cmp_ui_2exp(mpfr_srcptr b,unsigned long int i,mpfr_exp_t f)34d59437c0Smrg mpfr_cmp_ui_2exp (mpfr_srcptr b, unsigned long int i, mpfr_exp_t f)
35d59437c0Smrg {
36d59437c0Smrg   if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(b) ))
37d59437c0Smrg     {
38d59437c0Smrg       if (MPFR_IS_NAN (b))
39d59437c0Smrg         {
40299c6f0cSmrg           MPFR_SET_ERANGEFLAG ();
41d59437c0Smrg           return 0;
42d59437c0Smrg         }
43d59437c0Smrg       else if (MPFR_IS_INF(b))
44d59437c0Smrg         return MPFR_INT_SIGN (b);
45d59437c0Smrg       else /* since b cannot be NaN, b=0 here */
46d59437c0Smrg         return i != 0 ? -1 : 0;
47d59437c0Smrg     }
48d59437c0Smrg 
49d59437c0Smrg   if (MPFR_IS_NEG (b))
50d59437c0Smrg     return -1;
51d59437c0Smrg   /* now b > 0 */
52d59437c0Smrg   else if (MPFR_UNLIKELY(i == 0))
53d59437c0Smrg     return 1;
54d59437c0Smrg   else /* b > 0, i > 0 */
552ba2404bSmrg #ifdef MPFR_LONG_WITHIN_LIMB
56d59437c0Smrg     {
57d59437c0Smrg       mpfr_exp_t e;
58d59437c0Smrg       int k;
59d59437c0Smrg       mp_size_t bn;
60d59437c0Smrg       mp_limb_t c, *bp;
61d59437c0Smrg 
62d59437c0Smrg       /* i must be representable in a mp_limb_t */
63d59437c0Smrg       MPFR_ASSERTN(i == (mp_limb_t) i);
64d59437c0Smrg 
65d59437c0Smrg       e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */
66d59437c0Smrg       if (e <= f)
67d59437c0Smrg         return -1;
68d59437c0Smrg       if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS &&
69d59437c0Smrg           e > f + GMP_NUMB_BITS)
70d59437c0Smrg         return 1;
71d59437c0Smrg 
72d59437c0Smrg       /* now f < e <= f + GMP_NUMB_BITS */
73d59437c0Smrg       c = (mp_limb_t) i;
74d59437c0Smrg       count_leading_zeros(k, c);
75d59437c0Smrg       if ((int) (e - f) > GMP_NUMB_BITS - k)
76d59437c0Smrg         return 1;
77d59437c0Smrg       if ((int) (e - f) < GMP_NUMB_BITS - k)
78d59437c0Smrg         return -1;
79d59437c0Smrg 
80d59437c0Smrg       /* now b and i*2^f have the same exponent */
81d59437c0Smrg       c <<= k;
82d59437c0Smrg       bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
83d59437c0Smrg       bp = MPFR_MANT(b);
84d59437c0Smrg       if (bp[bn] > c)
85d59437c0Smrg         return 1;
86d59437c0Smrg       if (bp[bn] < c)
87d59437c0Smrg         return -1;
88d59437c0Smrg 
89d59437c0Smrg       /* most significant limbs agree, check remaining limbs from b */
90d59437c0Smrg       while (bn > 0)
91d59437c0Smrg         if (bp[--bn] != 0)
92d59437c0Smrg           return 1;
93d59437c0Smrg       return 0;
94d59437c0Smrg     }
952ba2404bSmrg #else
962ba2404bSmrg   {
972ba2404bSmrg       mpfr_t uu;
982ba2404bSmrg       int ret;
992ba2404bSmrg       MPFR_SAVE_EXPO_DECL (expo);
1002ba2404bSmrg 
1012ba2404bSmrg       mpfr_init2 (uu, sizeof (unsigned long) * CHAR_BIT);
1022ba2404bSmrg       /* Warning: i*2^f might be outside the current exponent range! */
1032ba2404bSmrg       MPFR_SAVE_EXPO_MARK (expo);
1042ba2404bSmrg       mpfr_set_ui_2exp (uu, i, f, MPFR_RNDZ);
1052ba2404bSmrg       MPFR_SAVE_EXPO_FREE (expo);
1062ba2404bSmrg       ret = mpfr_cmp (b, uu);
1072ba2404bSmrg       mpfr_clear (uu);
1082ba2404bSmrg       return ret;
1092ba2404bSmrg   }
1102ba2404bSmrg #endif /* MPFR_LONG_WITHIN_LIMB */
111d59437c0Smrg }
112d59437c0Smrg 
113d59437c0Smrg #undef mpfr_cmp_ui
114d59437c0Smrg int
mpfr_cmp_ui(mpfr_srcptr b,unsigned long int i)115d59437c0Smrg mpfr_cmp_ui (mpfr_srcptr b, unsigned long int i)
116d59437c0Smrg {
117d59437c0Smrg   return mpfr_cmp_ui_2exp (b, i, 0);
118d59437c0Smrg }
119