summaryrefslogtreecommitdiff
path: root/mpz/cmpabs_d.c
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2001-05-03 00:38:20 +0200
committerKevin Ryde <user42@zip.com.au>2001-05-03 00:38:20 +0200
commite7f5647c548d21e927adbe6f56c3159363bfb2c1 (patch)
tree1b123e46bc9cf02d11d1ab7416847b25ce1478d1 /mpz/cmpabs_d.c
parent5a6637d60cca0ec5d0ab76fbe4fec2dfbc4f5269 (diff)
downloadgmp-e7f5647c548d21e927adbe6f56c3159363bfb2c1.tar.gz
Replacement of:
* mpz/cmp_d.c, mpz/cmpabs_d.c: New files. Don't use mpf functions from mpz. Also take advantage of the small value of LIMBS_PER_DOUBLE to unroll the compare loop.
Diffstat (limited to 'mpz/cmpabs_d.c')
-rw-r--r--mpz/cmpabs_d.c86
1 files changed, 74 insertions, 12 deletions
diff --git a/mpz/cmpabs_d.c b/mpz/cmpabs_d.c
index 9cc45b5c3..b023ac714 100644
--- a/mpz/cmpabs_d.c
+++ b/mpz/cmpabs_d.c
@@ -23,24 +23,86 @@ MA 02111-1307, USA.
#include "gmp.h"
#include "gmp-impl.h"
+
+#define RETURN_CMP(zl, dl) \
+ do { \
+ zlimb = (zl); \
+ dlimb = (dl); \
+ if (zlimb != dlimb) \
+ return (zlimb >= dlimb ? 1 : -1); \
+ } while (0)
+
+#define RETURN_NONZERO(ptr, size, val) \
+ do { \
+ mp_size_t __i; \
+ for (__i = (size)-1; __i >= 0; __i--) \
+ if ((ptr)[__i] != 0) \
+ return val; \
+ return 0; \
+ } while (0)
+
+
int
mpz_cmpabs_d (mpz_srcptr z, double d)
{
- mp_limb_t darray[LIMBS_PER_DOUBLE];
- mpf_t u, v;
- int zsize;
+ mp_limb_t darray[LIMBS_PER_DOUBLE], zlimb, dlimb;
+ mp_srcptr zp;
+ int zsize, dexp;
- zsize = ABSIZ(z);
+ /* 1. Check for either operand zero. */
+ zsize = SIZ(z);
if (d == 0.0)
- return zsize;
+ return (zsize != 0);
+ if (zsize == 0)
+ return (d != 0 ? -1 : 0);
+
+ /* 2. Ignore signs. */
+ zsize = ABS(zsize);
+ d = ABS(d);
+
+ /* 3. Small d, knowing abs(z) >= 1. */
+ if (d < 1.0)
+ return 1;
+
+ dexp = __gmp_extract_double (darray, d);
+ ASSERT (dexp >= 1);
+
+ /* 4. Check for different high limb positions. */
+ if (zsize != dexp)
+ return (zsize >= dexp ? 1 : -1);
+
+ /* 5. Limb data. */
+ zp = PTR(z);
+
+#if LIMBS_PER_DOUBLE == 2
+ RETURN_CMP (zp[zsize-1], darray[1]);
+ if (zsize == 1)
+ return (darray[0] != 0 ? -1 : 0);
+
+ RETURN_CMP (zp[zsize-2], darray[0]);
+ RETURN_NONZERO (zp, zsize-2, 1);
+
+#else
+#if LIMBS_PER_DOUBLE == 3
+ RETURN_CMP (zp[zsize-1], darray[2]);
+ if (zsize == 1)
+ return ((darray[0] | darray[1]) != 0 ? -1 : 0);
- SIZ(u) = zsize;
- EXP(u) = zsize;
- PTR(u) = PTR(z);
+ RETURN_CMP (zp[zsize-2], darray[1]);
+ if (zsize == 2)
+ return (darray[0] != 0 ? -1 : 0);
- PTR(v) = darray;
- SIZ(v) = LIMBS_PER_DOUBLE;
- EXP(v) = __gmp_extract_double (darray, ABS(d));
+ RETURN_CMP (zp[zsize-3], darray[0]);
+ RETURN_NONZERO (zp, zsize-3, 1);
- return mpf_cmp (u, v);
+#else
+ for (i = 1; i <= LIMBS_PER_DOUBLE; i++)
+ {
+ RETURN_CMP (zp[zsize-i], darray[LIMBS_PER_DOUBLE-i]);
+ if (i >= zsize)
+ RETURN_NONZERO (darray, LIMBS_PER_DOUBLE-i, -1);
+ }
+ RETURN_NONZERO (zp, zsize-LIMBS_PER_DOUBLE, 1);
+#endif
+#endif
}