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