cmp_d.c revision 1.1.1.3 1 1.1 mrg /* mpz_cmp_d -- compare absolute values of mpz and double.
2 1.1 mrg
3 1.1.1.3 mrg Copyright 2001-2003 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library.
6 1.1 mrg
7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
8 1.1.1.3 mrg it under the terms of either:
9 1.1.1.3 mrg
10 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free
11 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your
12 1.1.1.3 mrg option) any later version.
13 1.1.1.3 mrg
14 1.1.1.3 mrg or
15 1.1.1.3 mrg
16 1.1.1.3 mrg * the GNU General Public License as published by the Free Software
17 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any
18 1.1.1.3 mrg later version.
19 1.1.1.3 mrg
20 1.1.1.3 mrg or both in parallel, as here.
21 1.1 mrg
22 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
23 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 1.1.1.3 mrg for more details.
26 1.1 mrg
27 1.1.1.3 mrg You should have received copies of the GNU General Public License and the
28 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not,
29 1.1.1.3 mrg see https://www.gnu.org/licenses/. */
30 1.1 mrg
31 1.1 mrg #include "config.h"
32 1.1 mrg
33 1.1 mrg #if HAVE_FLOAT_H
34 1.1 mrg #include <float.h> /* for DBL_MAX */
35 1.1 mrg #endif
36 1.1 mrg
37 1.1 mrg #include "gmp.h"
38 1.1 mrg #include "gmp-impl.h"
39 1.1 mrg
40 1.1 mrg
41 1.1 mrg #define RETURN_CMP(zl, dl) \
42 1.1 mrg do { \
43 1.1 mrg zlimb = (zl); \
44 1.1 mrg dlimb = (dl); \
45 1.1 mrg if (zlimb != dlimb) \
46 1.1 mrg return (zlimb >= dlimb ? ret : -ret); \
47 1.1 mrg } while (0)
48 1.1 mrg
49 1.1 mrg #define RETURN_NONZERO(ptr, size, val) \
50 1.1 mrg do { \
51 1.1 mrg mp_size_t __i; \
52 1.1 mrg for (__i = (size)-1; __i >= 0; __i--) \
53 1.1 mrg if ((ptr)[__i] != 0) \
54 1.1 mrg return val; \
55 1.1 mrg return 0; \
56 1.1 mrg } while (0)
57 1.1 mrg
58 1.1 mrg
59 1.1 mrg int
60 1.1 mrg mpz_cmp_d (mpz_srcptr z, double d)
61 1.1 mrg {
62 1.1 mrg mp_limb_t darray[LIMBS_PER_DOUBLE], zlimb, dlimb;
63 1.1 mrg mp_srcptr zp;
64 1.1 mrg mp_size_t zsize;
65 1.1 mrg int dexp, ret;
66 1.1 mrg
67 1.1 mrg /* d=NaN is an invalid operation, there's no sensible return value.
68 1.1 mrg d=Inf or -Inf is always bigger than z. */
69 1.1 mrg DOUBLE_NAN_INF_ACTION (d, __gmp_invalid_operation (), goto z_zero);
70 1.1 mrg
71 1.1 mrg /* 1. Either operand zero. */
72 1.1 mrg zsize = SIZ(z);
73 1.1 mrg if (d == 0.0)
74 1.1 mrg return zsize;
75 1.1 mrg if (zsize == 0)
76 1.1 mrg {
77 1.1 mrg z_zero:
78 1.1 mrg return (d < 0.0 ? 1 : -1);
79 1.1 mrg }
80 1.1 mrg
81 1.1 mrg /* 2. Opposite signs. */
82 1.1 mrg if (zsize >= 0)
83 1.1 mrg {
84 1.1 mrg if (d < 0.0)
85 1.1.1.2 mrg return 1; /* >=0 cmp <0 */
86 1.1 mrg ret = 1;
87 1.1 mrg }
88 1.1 mrg else
89 1.1 mrg {
90 1.1 mrg if (d >= 0.0)
91 1.1.1.2 mrg return -1; /* <0 cmp >=0 */
92 1.1 mrg ret = -1;
93 1.1 mrg d = -d;
94 1.1 mrg zsize = -zsize;
95 1.1 mrg }
96 1.1 mrg
97 1.1 mrg /* 3. Small d, knowing abs(z) >= 1. */
98 1.1 mrg if (d < 1.0)
99 1.1 mrg return ret;
100 1.1 mrg
101 1.1 mrg dexp = __gmp_extract_double (darray, d);
102 1.1 mrg ASSERT (dexp >= 1);
103 1.1 mrg
104 1.1 mrg /* 4. Check for different high limb positions. */
105 1.1 mrg if (zsize != dexp)
106 1.1 mrg return (zsize >= dexp ? ret : -ret);
107 1.1 mrg
108 1.1 mrg /* 5. Limb data. */
109 1.1 mrg zp = PTR(z);
110 1.1 mrg
111 1.1 mrg #if LIMBS_PER_DOUBLE == 2
112 1.1 mrg RETURN_CMP (zp[zsize-1], darray[1]);
113 1.1 mrg if (zsize == 1)
114 1.1 mrg return (darray[0] != 0 ? -ret : 0);
115 1.1 mrg
116 1.1 mrg RETURN_CMP (zp[zsize-2], darray[0]);
117 1.1 mrg RETURN_NONZERO (zp, zsize-2, ret);
118 1.1 mrg #endif
119 1.1 mrg
120 1.1 mrg #if LIMBS_PER_DOUBLE == 3
121 1.1 mrg RETURN_CMP (zp[zsize-1], darray[2]);
122 1.1 mrg if (zsize == 1)
123 1.1 mrg return ((darray[0] | darray[1]) != 0 ? -ret : 0);
124 1.1 mrg
125 1.1 mrg RETURN_CMP (zp[zsize-2], darray[1]);
126 1.1 mrg if (zsize == 2)
127 1.1 mrg return (darray[0] != 0 ? -ret : 0);
128 1.1 mrg
129 1.1 mrg RETURN_CMP (zp[zsize-3], darray[0]);
130 1.1 mrg RETURN_NONZERO (zp, zsize-3, ret);
131 1.1 mrg #endif
132 1.1 mrg
133 1.1 mrg #if LIMBS_PER_DOUBLE >= 4
134 1.1 mrg {
135 1.1 mrg int i;
136 1.1 mrg for (i = 1; i <= LIMBS_PER_DOUBLE; i++)
137 1.1 mrg {
138 1.1 mrg RETURN_CMP (zp[zsize-i], darray[LIMBS_PER_DOUBLE-i]);
139 1.1 mrg if (i >= zsize)
140 1.1 mrg RETURN_NONZERO (darray, LIMBS_PER_DOUBLE-i, -ret);
141 1.1 mrg }
142 1.1 mrg RETURN_NONZERO (zp, zsize-LIMBS_PER_DOUBLE, ret);
143 1.1 mrg }
144 1.1 mrg #endif
145 1.1 mrg }
146