From 094b025ae88a1a79805734d58ef6bd75fc660f97 Mon Sep 17 00:00:00 2001 From: Artoria2e5 Date: Sun, 10 Mar 2024 19:06:09 +0800 Subject: [PATCH 1/4] add long long to zz.h (draft) --- include/NTL/ZZ.h | 14 ++++++++++++++ src/MakeDesc.cpp | 10 +++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/NTL/ZZ.h b/include/NTL/ZZ.h index b843b21..4937ecc 100644 --- a/include/NTL/ZZ.h +++ b/include/NTL/ZZ.h @@ -272,6 +272,20 @@ inline void conv(unsigned int& x, const ZZ& a) inline unsigned int to_uint(const ZZ& a) { return (unsigned int)(_ntl_gtouint(a.rep)); } +inline void conv(unsigned long& x, const ZZ& a) { x = _ntl_gtouint(a.rep); } +inline unsigned long to_ulong(const ZZ& a) { return _ntl_gtouint(a.rep); } + +#if NTL_BITS_PER_LONGLONG == NTL_BITS_PER_LONG +inline void conv(unsigned long long& x, const ZZ& a) { x = (unsigned long long) _ntl_gtouint(a.rep); } +inline unsigned long long to_ulonglong(const ZZ& a) { return (unsigned long long) _ntl_gtouint(a.rep); } +inline void conv(ZZ& x, unsigned long a) { _ntl_guintoz(a, &x.rep); } +inline ZZ to_ZZ(unsigned long a) { return ZZ(INIT_VAL, a); } +#elif NTL_BITS_PER_LONGLONG == (2*NTL_BITS_PER_LONG) +// FIXME: decide on: +// * do we want to expose double-width conversion (NTL_ULL_TYPE)? +// * do we want to have a signed version (create a NTL_LL_TYPE)? +#endif + inline void conv(double& x, const ZZ& a) { x = _ntl_gdoub(a.rep); } inline double to_double(const ZZ& a) { return _ntl_gdoub(a.rep); } diff --git a/src/MakeDesc.cpp b/src/MakeDesc.cpp index 0818e39..7909990 100644 --- a/src/MakeDesc.cpp +++ b/src/MakeDesc.cpp @@ -775,7 +775,7 @@ const char *yn_vec[2] = { "no", "yes" }; int main() { - long bpl, bpi, bpt, rs_arith, nbits, wnbits; + long bpl, bpll, bpi, bpt, rs_arith, nbits, wnbits; long nb_bpl; long dp, dr; long fma_detected; @@ -821,6 +821,13 @@ int main() } + /* + * compute bpl = bits per long long (not the same as NPL_ULL_TYPE) + * FIXME: find out why other code uses a loop to count bits + */ + + bpll = sizeof(long long) * CHAR_BIT; + /* * compute bpi = bits per int @@ -1207,6 +1214,7 @@ int main() fprintf(f, "#ifndef NTL_mach_desc__H\n"); fprintf(f, "#define NTL_mach_desc__H\n\n\n"); fprintf(f, "#define NTL_BITS_PER_LONG (%ld)\n", bpl); + fprintf(f, "#define NTL_BITS_PER_LONG_LONG (%ld)\n", bpll); fprintf(f, "#define NTL_NUMBITS_BPL (%ld)\n", nb_bpl); fprintf(f, "#define NTL_MAX_LONG (%ldL)\n", ((long) ((1UL<<(bpl-1))-1UL))); fprintf(f, "#define NTL_MAX_INT (%ld)\n", ((long) ((1UL<<(bpi-1))-1UL))); From 6397f7683d0ccd49a0ac20f0b847537b0ec7fb43 Mon Sep 17 00:00:00 2001 From: Artoria2e5 Date: Tue, 12 Mar 2024 13:53:43 +0800 Subject: [PATCH 2/4] fixup! do print long long length --- src/MakeDesc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MakeDesc.cpp b/src/MakeDesc.cpp index 7909990..9f2e8d8 100644 --- a/src/MakeDesc.cpp +++ b/src/MakeDesc.cpp @@ -1126,6 +1126,7 @@ int main() fprintf(stderr, "\n*** GOOD NEWS: compatible machine.\n"); fprintf(stderr, "summary of machine characteristics:\n"); fprintf(stderr, "bits per long = %ld\n", bpl); + fprintf(stderr, "bits per long long = %ld\n", bpll); fprintf(stderr, "bits per int = %ld\n", bpi); fprintf(stderr, "bits per size_t = %ld\n", bpt); fprintf(stderr, "arith right shift = %s\n", yn_vec[rs_arith]); From 1da4df8e19e6d1355ffe60b06297bb55d475ccb8 Mon Sep 17 00:00:00 2001 From: Artoria2e5 Date: Tue, 12 Mar 2024 13:54:54 +0800 Subject: [PATCH 3/4] Make NTL_LL_TYPE a thing --- doc/config.txt | 1 + include/NTL/ctools.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/doc/config.txt b/doc/config.txt index 985631a..57a9b05 100644 --- a/doc/config.txt +++ b/doc/config.txt @@ -400,6 +400,7 @@ NTL_LEGACY_INPUT_ERROR=off NTL_LEGACY_SP_MULMOD=off +NTL_SIGNED_LONG_LONG_TYPE=undefined NTL_UNSIGNED_LONG_LONG_TYPE=undefined NTL_CLEAN_INT=off NTL_CLEAN_PTR=on diff --git a/include/NTL/ctools.h b/include/NTL/ctools.h index 0c77c53..1af6d6a 100644 --- a/include/NTL/ctools.h +++ b/include/NTL/ctools.h @@ -74,20 +74,24 @@ #elif (NTL_BITS_PER_LONG == 64 && defined(__GNUC__)) +#define NTL_LL_TYPE __int128_t #define NTL_ULL_TYPE __uint128_t #elif (NTL_BITS_PER_LONG == 32 && (defined(_MSC_VER) || defined(__BORLANDC__))) +#define NTL_LL_TYPE __int64 #define NTL_ULL_TYPE unsigned __int64 #elif (NTL_BITS_PER_LONG == 64 && (defined(_MSC_VER) || defined(__BORLANDC__))) +#define NTL_LL_TYPE __int64 #define NTL_ULL_TYPE unsigned __int128 #endif #if (!defined(NTL_ULL_TYPE)) +#define NTL_LL_TYPE long long #define NTL_ULL_TYPE unsigned long long #endif @@ -95,14 +99,17 @@ #ifdef NTL_HAVE_LL_TYPE +typedef NTL_LL_TYPE _ntl_longlong; typedef NTL_ULL_TYPE _ntl_ulonglong; // typenames are more convenient than macros #else #undef NTL_ULL_TYPE +#undef NTL_LL_TYPE // prevent any use of these macros +class _ntl_longlong { private: _ntl_longlong() { } }; class _ntl_ulonglong { private: _ntl_ulonglong() { } }; // cannot create variables of these types From f8df0cf40fd8e95e45f16e76dd293a309c67a14a Mon Sep 17 00:00:00 2001 From: Artoria2e5 Date: Tue, 12 Mar 2024 13:55:25 +0800 Subject: [PATCH 4/4] lip.{cpp,h}: add LL functions, terribly --- include/NTL/ZZ.h | 13 +++-- include/NTL/lip.h | 16 ++++- src/lip.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 161 insertions(+), 14 deletions(-) diff --git a/include/NTL/ZZ.h b/include/NTL/ZZ.h index 4937ecc..c71d2a2 100644 --- a/include/NTL/ZZ.h +++ b/include/NTL/ZZ.h @@ -278,12 +278,13 @@ inline unsigned long to_ulong(const ZZ& a) { return _ntl_gtouint(a.rep); } #if NTL_BITS_PER_LONGLONG == NTL_BITS_PER_LONG inline void conv(unsigned long long& x, const ZZ& a) { x = (unsigned long long) _ntl_gtouint(a.rep); } inline unsigned long long to_ulonglong(const ZZ& a) { return (unsigned long long) _ntl_gtouint(a.rep); } -inline void conv(ZZ& x, unsigned long a) { _ntl_guintoz(a, &x.rep); } -inline ZZ to_ZZ(unsigned long a) { return ZZ(INIT_VAL, a); } -#elif NTL_BITS_PER_LONGLONG == (2*NTL_BITS_PER_LONG) -// FIXME: decide on: -// * do we want to expose double-width conversion (NTL_ULL_TYPE)? -// * do we want to have a signed version (create a NTL_LL_TYPE)? +inline void conv(ZZ& x, unsigned long long a) { _ntl_guintoz(a, &x.rep); } +inline ZZ to_ZZ(unsigned long long a) { return ZZ(INIT_VAL, a); } +#elif (NTL_BITS_PER_LONGLONG == (2*NTL_BITS_PER_LONG)) && defined (NTL_HAVE_LL_TYPE) +inline void conv(unsigned long long& x, const ZZ& a) { x = (unsigned long long) _ntl_gtoudint(a.rep); } +inline unsigned long long to_ulonglong(const ZZ& a) { return (unsigned long long) _ntl_gtoudint(a.rep); } +inline void conv(ZZ& x, unsigned long long a) { _ntl_gudintoz(a, &x.rep); } +inline ZZ to_ZZ(unsigned long long a) { return ZZ(INIT_VAL, a); } #endif inline void conv(double& x, const ZZ& a) { x = _ntl_gdoub(a.rep); } diff --git a/include/NTL/lip.h b/include/NTL/lip.h index 808c92a..09bc1c3 100644 --- a/include/NTL/lip.h +++ b/include/NTL/lip.h @@ -416,7 +416,6 @@ inline long _ntl_PINNED(_ntl_gbigint p) void _ntl_gintoz(long d, _ntl_gbigint *a); /* *a = d; */ - void _ntl_guintoz(unsigned long d, _ntl_gbigint *a); /* *a = d; space is allocated */ @@ -428,8 +427,21 @@ inline long _ntl_PINNED(_ntl_gbigint p) /* converts a to a long; overflow results in value mod 2^{NTL_BITS_PER_LONG}. */ - +#ifdef NTL_HAVE_LL_TYPE + void ntl_gdintoz(NTL_LL_TYPE d, _ntl_gbigint *a); + /* *a = d; */ + + void ntl_gudintoz(NTL_ULL_TYPE d, _ntl_gbigint *a); + /* *a = d; space is allocated */ + + NTL_LL_TYPE _ntl_gtodint(_ntl_gbigint a); + /* converts a to a double-word type; overflow results in value + mod 2^{2 * NTL_BITS_PER_LONG}. */ + NTL_ULL_TYPE _ntl_gtoudint(_ntl_gbigint a); + /* converts a to a double-word type; overflow results in value + mod 2^{2 * NTL_BITS_PER_LONG}. */ +#endif double _ntl_gdoub(_ntl_gbigint n); /* converts a to a double; no overflow check */ diff --git a/src/lip.cpp b/src/lip.cpp index fb2c8cd..2508869 100644 --- a/src/lip.cpp +++ b/src/lip.cpp @@ -113,6 +113,17 @@ ABS(long x) return _ntl_limb_t(x); } +#ifdef NTL_HAVE_LL_TYPE +static inline _ntl_longlong +ABS(_ntl_longlong x) +{ + if (x < 0) + return -_ntl_longlong(x); // careful ! + else + return _ntl_longlong(x); +} +#endif + static inline long XOR(long a, long b) { @@ -2178,18 +2189,12 @@ void _ntl_guintoz(unsigned long d, _ntl_gbigint *aa) #endif - - long _ntl_gtoint(_ntl_gbigint a) { unsigned long res = _ntl_gtouint(a); return cast_signed(res); } - - - - #if (NTL_ZZ_NBITS >= NTL_BITS_PER_LONG) unsigned long _ntl_gtouint(_ntl_gbigint a) @@ -2230,6 +2235,135 @@ unsigned long _ntl_gtouint(_ntl_gbigint a) #endif +#ifdef NTL_HAVE_LL_TYPE +#if (NTL_ZZ_NBITS >= (NTL_BITS_PER_LONG * 2)) +// Unlikely, but it's the simple case, so. +void _ntl_gdintoz(NTL_LL_TYPE d, _ntl_gbigint *aa) +{ + _ntl_gbigint a = *aa; + + if (d == 0) { + if (a) SIZE(a) = 0; + } + else { + if (!a) { + _ntl_gsetlength(&a, 1); + *aa = a; + } + + SIZE(a) = d < 0 ? -1 : 1; + DATA(a)[0] = ABS(d); + } +} + +#else + +void _ntl_gdintoz(NTL_LL_TYPE d, _ntl_gbigint *aa) +{ + long sa, i; + NTL_LL_TYPE d1; + // Keeping the assumption NTL_BITS_PER_LIMB_T >= BITS_PER_LONG, + // we split something the size of BITS_PER_LONG*2 into two limbs + _ntl_limb_t d1l, d1h, d2; + + _ntl_gbigint a = *aa; + + if (d == 0) { + if (a) SIZE(a) = 0; + return; + } + + d1 = ABS(d); + d1l = d1 & NTL_LIMB_MASK; + d1h = (d1 >> NTL_BITS_PER_LIMB_T) & NTL_LIMB_MASK; + + sa = 0; + d2 = d1h; + do { + d2 >>= NTL_ZZ_NBITS; + sa++; + } + while (d2); + d2 = d1l; + do { + d2 >>= NTL_ZZ_NBITS; + sa++; + } + while (d2); + + if (MustAlloc(a, sa)) { + _ntl_gsetlength(&a, sa); + *aa = a; + } + + _ntl_limb_t *adata = DATA(a); + + // This is an abomination. I'm sorry. + for (i = 0; i < sa && d1h; i++) { + adata[i] = CLIP(d1h); + d1h >>= NTL_ZZ_NBITS; + } + for (; i < sa; i++) { + adata[i] = CLIP(d1l); + d1l >>= NTL_ZZ_NBITS; + } + + if (d < 0) sa = -sa; + SIZE(a) = sa; +} +#endif +// (NTL_ZZ_NBITS >= (NTL_BITS_PER_LONG * 2)) + +// And vice versa for _ntl_gduintoz. I think it's just the ABS that's different? + +NTL_LL_TYPE _ntl_gtodint(_ntl_gbigint a) +{ + NTL_ULL_TYPE res = _ntl_gtoudint(a); + return res; // FIXME: cast_signed, probably not that urgent. +} + +#if (NTL_ZZ_NBITS >= (NTL_BITS_PER_LONG * 2)) +// Still unlikely. +NTL_ULL_TYPE _ntl_gtoudint(_ntl_gbigint a) +{ + if (ZEROP(a)) + return 0; + + if (SIZE(a) > 0) + return DATA(a)[0]; + + return -DATA(a)[0]; +} + +#else + +NTL_ULL_TYPE _ntl_gtoudint(_ntl_gbigint a) +{ + if (ZEROP(a)) + return 0; + + long sa, aneg; + _ntl_limb_t *adata; + GET_SIZE_NEG(sa, aneg, a); + adata = DATA(a); + + NTL_ULL_TYPE d = adata[0]; + long bits = NTL_ZZ_NBITS; + long i = 1; + while (bits < (NTL_BITS_PER_LONG * 2) && i < sa) { + d |= adata[i] << bits; + bits += NTL_ZZ_NBITS; + i++; + } + + if (aneg) d = -d; + return d; +} + +#endif +#endif +// defined(NTL_HAVE_LL_TYPE) +