1 /* mpfr_cmp2 -- exponent shift when subtracting two numbers.
2
3 Copyright 1999-2004, 2006-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23
24 #define MPFR_NEED_LONGLONG_H
25 #include "mpfr-impl.h"
26
27 /* If |b| != |c|, puts the number of canceled bits when one subtracts |c|
28 from |b| in *cancel. Returns the sign of the difference (-1, 0, 1).
29
30 Assumes neither of b or c is NaN, +/- infinity, or +/- 0.
31
32 In other terms, if |b| != |c|, mpfr_cmp2 (b, c) stores
33 EXP(max(|b|,|c|)) - EXP(|b| - |c|) in *cancel.
34
35 One necessarily has 0 <= cancel <= max(PREC(b),PREC(c)), so that this
36 value is representable in a mpfr_prec_t. Note that in the code, the
37 maximum intermediate value is cancel + 1, but since MPFR_PREC_MAX is
38 not the maximum value of mpfr_prec_t, there is no integer overflow.
39 */
40
41 int
mpfr_cmp2(mpfr_srcptr b,mpfr_srcptr c,mpfr_prec_t * cancel)42 mpfr_cmp2 (mpfr_srcptr b, mpfr_srcptr c, mpfr_prec_t *cancel)
43 {
44 mp_limb_t *bp, *cp, bb, cc, lastc, dif;
45 int high_dif; /* manipulated like a boolean */
46 mp_size_t bn, cn;
47 mpfr_exp_t sdiff_exp;
48 mpfr_uexp_t diff_exp;
49 mpfr_prec_t res = 0; /* will be the number of canceled bits (*cancel) */
50 int sign;
51
52 /* b=c should not happen, since cmp2 is called only from agm (with
53 different variables) and from sub1 (if b=c, then sub1sp would be
54 called instead). So, no need for a particular optimization here. */
55
56 /* the cases b=0 or c=0 are also treated apart in agm and sub
57 (which calls sub1) */
58 MPFR_ASSERTD (MPFR_IS_PURE_UBF (b));
59 MPFR_ASSERTD (MPFR_IS_PURE_UBF (c));
60
61 sdiff_exp = MPFR_UNLIKELY (MPFR_IS_UBF (b) || MPFR_IS_UBF (c)) ?
62 mpfr_ubf_diff_exp (b, c) : MPFR_GET_EXP (b) - MPFR_GET_EXP (c);
63
64 /* The returned result is saturated to [MPFR_EXP_MIN,MPFR_EXP_MAX],
65 which is the range of the mpfr_exp_t type. But under the condition
66 below, since |MPFR_EXP_MIN| >= MPFR_EXP_MAX, the value of cancel
67 will not be affected: by symmetry (as done in the code), assume
68 |b| >= |c|; if EXP(b) - EXP(c) >= MPFR_EXP_MAX, then |c| < ulp(b),
69 so that the value of cancel is 0, or 1 if |b| is a power of 2,
70 whatever the exact value of EXP(b) - EXP(c). */
71 MPFR_STAT_STATIC_ASSERT (MPFR_EXP_MAX > MPFR_PREC_MAX);
72
73 if (sdiff_exp >= 0)
74 {
75 sign = 1; /* assumes |b| > |c|; will be changed if not. */
76 diff_exp = sdiff_exp;
77
78 bp = MPFR_MANT(b);
79 cp = MPFR_MANT(c);
80
81 /* index of the most significant limb of b and c */
82 bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
83 cn = (MPFR_PREC(c) - 1) / GMP_NUMB_BITS;
84
85 /* If diff_exp != 0, i.e. diff_exp > 0, then |b| > |c|. Otherwise... */
86 if (diff_exp == 0)
87 {
88 /* Skip the identical most significant limbs, adding GMP_NUMB_BITS
89 to the number of canceled bits at each iteration. */
90 while (bn >= 0 && cn >= 0 && bp[bn] == cp[cn])
91 {
92 bn--;
93 cn--;
94 res += GMP_NUMB_BITS;
95 }
96
97 if (MPFR_UNLIKELY (bn < 0))
98 {
99 if (MPFR_LIKELY (cn < 0)) /* |b| = |c| */
100 return 0;
101
102 /* b has been read entirely, but not c. Thus |b| <= |c|.
103 Swap (bp,bn) and (cp,cn), and take the opposite sign
104 for the symmetric case below (simulating a swap).
105 Note: cp will not be used, thus is not assigned; and
106 "cn = -1;" is necessary to enter the following "if"
107 (probably less confusing than a "goto"). */
108 bp = cp;
109 bn = cn;
110 cn = -1;
111 sign = -1;
112 }
113
114 if (MPFR_UNLIKELY (cn < 0))
115 /* c discards exactly the upper part of b */
116 {
117 int z;
118
119 MPFR_ASSERTD (bn >= 0);
120
121 /* Skip null limbs of b (= non-represented null limbs of c),
122 adding GMP_NUMB_BITS to the number of canceled bits at
123 each iteration. */
124 while (bp[bn] == 0)
125 {
126 if (--bn < 0) /* |b| = |c| */
127 return 0;
128 res += GMP_NUMB_BITS;
129 }
130
131 count_leading_zeros (z, bp[bn]); /* bp[bn] != 0 */
132 *cancel = res + z;
133 return sign;
134 }
135
136 MPFR_ASSERTD (bn >= 0);
137 MPFR_ASSERTD (cn >= 0);
138 MPFR_ASSERTD (bp[bn] != cp[cn]);
139
140 /* |b| != |c|. If |b| < |c|: swap (bp,bn) and (cp,cn),
141 and take the opposite sign. */
142 if (bp[bn] < cp[cn])
143 {
144 mp_limb_t *tp;
145 mp_size_t tn;
146
147 tp = bp; bp = cp; cp = tp;
148 tn = bn; bn = cn; cn = tn;
149 sign = -1;
150 }
151 }
152 } /* MPFR_EXP(b) >= MPFR_EXP(c) */
153 else /* MPFR_EXP(b) < MPFR_EXP(c) */
154 {
155 /* We necessarily have |b| < |c|. Simulate a swap by reading the
156 parameters so that |(bp,bn)| > |(cp,cn)|. */
157
158 sign = -1;
159 diff_exp = - (mpfr_uexp_t) sdiff_exp;
160
161 bp = MPFR_MANT(c);
162 cp = MPFR_MANT(b);
163
164 bn = (MPFR_PREC(c) - 1) / GMP_NUMB_BITS;
165 cn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
166 }
167
168 /* Now we have removed the identical upper limbs of b and c
169 (when diff_exp = 0), and after the possible swap, we have |b| > |c|,
170 where b is represented by (bp,bn) and c is represented by (cp,cn).
171 The value diff_exp = EXP(b) - EXP(c) can be regarded as the number
172 of leading zeros of c, when aligned with b. */
173
174 /* When a limb of c is read from memory, the part that is not taken
175 into account for the operation with a limb bp[bn] of b will be put
176 in lastc, shifted to the leftmost part (for alignment with b):
177 [-------- bp[bn] --------][------- bp[bn-1] -------]
178 [-- old_lastc --][-------- cp[cn] --------]
179 [-- new_lastc --]
180 Note: if diff_exp == 0, then lastc will always remain 0. */
181 lastc = 0;
182
183 /* Compute the next limb difference, which cannot be 0 (dif >= 1). */
184
185 if (MPFR_LIKELY (diff_exp < GMP_NUMB_BITS))
186 {
187 cc = cp[cn] >> diff_exp;
188 /* warning: a shift by GMP_NUMB_BITS is not allowed by ISO C */
189 if (diff_exp != 0)
190 lastc = cp[cn] << (GMP_NUMB_BITS - diff_exp);
191 cn--;
192 }
193 else
194 {
195 cc = 0;
196 diff_exp -= GMP_NUMB_BITS; /* remove GMP_NUMB_BITS leading zeros */
197 }
198
199 MPFR_ASSERTD (bp[bn] >= cc); /* no borrow out in subtraction below */
200 dif = bp[bn--] - cc;
201 MPFR_ASSERTD (dif >= 1);
202 high_dif = 0;
203
204 /* The current difference, here and later, is expressed under the form
205 [high_dif][dif], where high_dif is 0 or 1, and dif is a limb.
206 Here, since we have computed a difference of limbs (with b >= c),
207 high_dif = 0. */
208
209 /* One needs to accumulate canceled bits for the remaining case where
210 b and c are close to each other due to a long borrow propagation:
211 b = [common part]1000...000[low(b)]
212 c = [common part]0111...111[low(c)]
213 After eliminating the common part above, we have computed a difference
214 of the most significant parts, which has been stored in [high_dif][dif]
215 with high_dif = 0. We will loop as long as the currently computed
216 difference [high_dif][dif] = 1 (it is >= 1 by construction). The
217 computation of the difference will be:
218 1bbb...bbb
219 - ccc...ccc
220 where the leading 1 before bbb...bbb corresponds to [high_dif][dif]
221 at the beginning of the loop. We will exit the loop also when c has
222 entirely been taken into account as cancellation is no longer possible
223 in this case (it is no longer possible to cancel the leading 1).
224 Note: We can enter the loop only with diff_exp = 0 (with a non-empty
225 common part, partly or entirely removed) or with diff_exp = 1 (with
226 an empty common part). Indeed, if diff_exp > 1, then no limbs have
227 been skipped, so that bp[bn] had its MSB equal to 1 and the most two
228 significant bits of cc are 0, which implies that dif > 1. */
229
230 while (MPFR_UNLIKELY ((cn >= 0 || lastc != 0)
231 && high_dif == 0 && dif == 1))
232 {
233 /* Since we consider the next limb, we assume a cancellation of
234 GMP_NUMB_BITS (the new exponent of the difference now being the
235 one of the MSB of the next limb). But if the leading 1 remains
236 1 in the difference (i.e. high_dif = 1 at the end of the loop),
237 then we will need to decrease res. */
238 res += GMP_NUMB_BITS;
239 MPFR_ASSERTD (diff_exp <= 1); /* see comment before the loop */
240 bb = bn >= 0 ? bp[bn--] : 0; /* next limb of b or non-represented 0 */
241 if (MPFR_UNLIKELY (cn < 0))
242 {
243 cc = lastc;
244 lastc = 0;
245 }
246 else if (diff_exp == 0)
247 {
248 cc = cp[cn--];
249 }
250 else
251 {
252 MPFR_ASSERTD (diff_exp == 1);
253 MPFR_ASSERTD (lastc == 0 || lastc == MPFR_LIMB_HIGHBIT);
254 cc = lastc + (cp[cn] >> 1);
255 lastc = cp[cn--] << (GMP_NUMB_BITS - 1);
256 }
257 dif = bb - cc;
258 high_dif = bb >= cc;
259 }
260
261 /* Now, c has entirely been taken into account or [high_dif][dif] > 1.
262 In any case, [high_dif][dif] >= 1 by construction.
263 First, we determine the currently number of canceled bits,
264 corresponding to the exponent of the current difference.
265 The trailing bits of c, if any, can still decrease the exponent of
266 the difference when [high_dif][dif] is a power of two, but since
267 [high_dif][dif] > 1 in this case, by not more than 1. */
268
269 if (high_dif != 0) /* high_dif == 1 */
270 {
271 res--; /* see comment at the beginning of the above loop */
272 MPFR_ASSERTD (res >= 0);
273 /* Terminate if [high_dif][dif] is not a power of two. */
274 if (MPFR_LIKELY (dif != 0))
275 goto end;
276 }
277 else /* high_dif == 0 */
278 {
279 int z;
280
281 MPFR_ASSERTD (dif >= 1); /* [high_dif][dif] >= 1 */
282 count_leading_zeros (z, dif);
283 res += z;
284 /* Terminate if [high_dif][dif] is not a power of two. */
285 if (MPFR_LIKELY (NOT_POW2 (dif)))
286 goto end;
287 }
288
289 /* Now, the result will be res + (low(b) < low(c)). */
290
291 /* If c has entirely been taken into account, it can no longer modify
292 the current result. */
293 if (cn < 0 && lastc == 0)
294 goto end;
295
296 for (; bn >= 0 ; bn--)
297 {
298 if (diff_exp >= GMP_NUMB_BITS)
299 {
300 diff_exp -= GMP_NUMB_BITS;
301 MPFR_ASSERTD (cc == 0);
302 }
303 else if (MPFR_UNLIKELY (cn < 0))
304 {
305 cc = lastc;
306 lastc = 0;
307 }
308 else if (diff_exp == 0)
309 {
310 cc = cp[cn--];
311 }
312 else
313 {
314 MPFR_ASSERTD (diff_exp >= 1 && diff_exp < GMP_NUMB_BITS);
315 cc = lastc + (cp[cn] >> diff_exp);
316 lastc = cp[cn--] << (GMP_NUMB_BITS - diff_exp);
317 }
318
319 if (bp[bn] != cc)
320 {
321 res += bp[bn] < cc;
322 goto end;
323 }
324 }
325
326 /* b has entirely been read. Determine whether the trailing part of c
327 is non-zero. */
328
329 if (lastc != 0)
330 res++;
331 else
332 {
333 while (cn >= 0 && cp[cn] == 0)
334 cn--;
335 if (cn >= 0)
336 res++;
337 }
338
339 end:
340 *cancel = res;
341 return sign;
342 }
343