Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add long long to zz.h (draft) #29

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions include/NTL/ZZ.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,21 @@ 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 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
Copy link
Author

@Artoria2e5 Artoria2e5 Mar 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to always offer _ntl_gtoudint using the NTL_ULL_TYPE too... right now vigna/CPRNG makes its own int128 routines. or is that too greedy?


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); }

Expand Down
7 changes: 7 additions & 0 deletions include/NTL/ctools.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,35 +74,42 @@

#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


#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

Expand Down
16 changes: 14 additions & 2 deletions include/NTL/lip.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand All @@ -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 */
Expand Down
11 changes: 10 additions & 1 deletion src/MakeDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1119,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]);
Expand Down Expand Up @@ -1207,6 +1215,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)));
Expand Down
146 changes: 140 additions & 6 deletions src/lip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)




Expand Down