blob: cddb9d508699057d9a470fe360cf754e0689473e [file] [log] [blame]
Austin Schuhdace2a62020-08-18 10:56:48 -07001/* mpf_eq -- Compare two floats up to a specified bit #.
2
3Copyright 1993, 1995, 1996, 2001, 2002, 2008, 2009, 2012 Free Software
4Foundation, Inc.
5
6This file is part of the GNU MP Library.
7
8The GNU MP Library is free software; you can redistribute it and/or modify
9it under the terms of either:
10
11 * the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
14
15or
16
17 * the GNU General Public License as published by the Free Software
18 Foundation; either version 2 of the License, or (at your option) any
19 later version.
20
21or both in parallel, as here.
22
23The GNU MP Library is distributed in the hope that it will be useful, but
24WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26for more details.
27
28You should have received copies of the GNU General Public License and the
29GNU Lesser General Public License along with the GNU MP Library. If not,
30see https://www.gnu.org/licenses/. */
31
32#include "gmp-impl.h"
33#include "longlong.h"
34
35int
36mpf_eq (mpf_srcptr u, mpf_srcptr v, mp_bitcnt_t n_bits)
37{
38 mp_srcptr up, vp, p;
39 mp_size_t usize, vsize, minsize, maxsize, n_limbs, i, size;
40 mp_exp_t uexp, vexp;
41 mp_limb_t diff;
42 int cnt;
43
44 uexp = u->_mp_exp;
45 vexp = v->_mp_exp;
46
47 usize = u->_mp_size;
48 vsize = v->_mp_size;
49
50 /* 1. Are the signs different? */
51 if ((usize ^ vsize) >= 0)
52 {
53 /* U and V are both non-negative or both negative. */
54 if (usize == 0)
55 return vsize == 0;
56 if (vsize == 0)
57 return 0;
58
59 /* Fall out. */
60 }
61 else
62 {
63 /* Either U or V is negative, but not both. */
64 return 0;
65 }
66
67 /* U and V have the same sign and are both non-zero. */
68
69 /* 2. Are the exponents different? */
70 if (uexp != vexp)
71 return 0;
72
73 usize = ABS (usize);
74 vsize = ABS (vsize);
75
76 up = u->_mp_d;
77 vp = v->_mp_d;
78
79 up += usize; /* point just above most significant limb */
80 vp += vsize; /* point just above most significant limb */
81
82 count_leading_zeros (cnt, up[-1]);
83 if ((vp[-1] >> (GMP_LIMB_BITS - 1 - cnt)) != 1)
84 return 0; /* msb positions different */
85
86 n_bits += cnt - GMP_NAIL_BITS;
87 n_limbs = (n_bits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
88
89 usize = MIN (usize, n_limbs);
90 vsize = MIN (vsize, n_limbs);
91
92#if 0
93 /* Ignore zeros at the low end of U and V. */
94 while (up[0] == 0)
95 up++, usize--;
96 while (vp[0] == 0)
97 vp++, vsize--;
98#endif
99
100 minsize = MIN (usize, vsize);
101 maxsize = usize + vsize - minsize;
102
103 up -= minsize; /* point at most significant common limb */
104 vp -= minsize; /* point at most significant common limb */
105
106 /* Compare the most significant part which has explicit limbs for U and V. */
107 for (i = minsize - 1; i > 0; i--)
108 {
109 if (up[i] != vp[i])
110 return 0;
111 }
112
113 n_bits -= (maxsize - 1) * GMP_NUMB_BITS;
114
115 size = maxsize - minsize;
116 if (size != 0)
117 {
118 if (up[0] != vp[0])
119 return 0;
120
121 /* Now either U or V has its limbs consumed, i.e, continues with an
122 infinite number of implicit zero limbs. Check that the other operand
123 has just zeros in the corresponding, relevant part. */
124
125 if (usize > vsize)
126 p = up - size;
127 else
128 p = vp - size;
129
130 for (i = size - 1; i > 0; i--)
131 {
132 if (p[i] != 0)
133 return 0;
134 }
135
136 diff = p[0];
137 }
138 else
139 {
140 /* Both U or V has its limbs consumed. */
141
142 diff = up[0] ^ vp[0];
143 }
144
145 if (n_bits < GMP_NUMB_BITS)
146 diff >>= GMP_NUMB_BITS - n_bits;
147
148 return diff == 0;
149}