Jeroen Demeyer on Wed, 06 Apr 2016 16:37:54 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Fix itos() for LONG_MIN |
Cheers, Jeroen.
>From 0716c072db8e50aad2edfb770d76f579e6e04134 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer <jdemeyer@cage.ugent.be> Date: Wed, 6 Apr 2016 16:09:08 +0200 Subject: [PATCH] Fix itos() for LONG_MIN --- doc/usersch5.tex | 5 +---- src/headers/pariinl.h | 8 +++++++- src/kernel/none/level1.h | 27 ++++++++++++++++++--------- src/language/es.c | 2 +- src/test/32/arith | 1 + src/test/in/arith | 1 + 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/doc/usersch5.tex b/doc/usersch5.tex index 5b51ca2..f3a557a 100644 --- a/doc/usersch5.tex +++ b/doc/usersch5.tex @@ -2233,10 +2233,7 @@ possible, otherwise raise an exception. \fun{long}{itos_or_0}{GEN x} converts the \typ{INT}~\kbd{x} to a \kbd{long} if possible, otherwise return $0$. -\fun{int}{is_bigint}{GEN n} true if \kbd{itos(n)} would succeed. - -\fun{int}{is_bigint_lg}{GEN n, long l} true if \kbd{itos(n)} would succeed. -Assumes \kbd{lgefint(n)} is equal to \kbd{l}. +\fun{int}{is_bigint}{GEN n} true if \kbd{itos(n)} would give an error. \fun{ulong}{itou}{GEN x} converts the \typ{INT}~\kbd{|x|} to an \kbd{ulong} if possible, otherwise raise an exception. diff --git a/src/headers/pariinl.h b/src/headers/pariinl.h index dc48cf9..16784e5 100644 --- a/src/headers/pariinl.h +++ b/src/headers/pariinl.h @@ -1841,7 +1841,13 @@ INLINE int equalim1(GEN n) INLINE int is_pm1(GEN n) { return lgefint(n) == 3 && n[2] == 1; } INLINE int is_bigint(GEN n) -{ long l = lgefint(n); return l > 3 || (l == 3 && (n[2] & HIGHBIT)); } +{ + pari_ulong u; + long l = lgefint(n); + if (l != 3) return (l > 3); + u = n[2]; + return (u > HIGHBIT) || (u == HIGHBIT && signe(n) >= 0); +} INLINE int odd(long x) { return x & 1; } INLINE int both_odd(long x, long y) { return x & y & 1; } diff --git a/src/kernel/none/level1.h b/src/kernel/none/level1.h index 99b849d..f7b90b0 100644 --- a/src/kernel/none/level1.h +++ b/src/kernel/none/level1.h @@ -308,21 +308,30 @@ uutoineg(ulong x, ulong y) INLINE long itos(GEN x) { - long s = signe(x); - long u; + long n; - if (!s) return 0; - u = x[2]; - if (lgefint(x) > 3 || u < 0) + if (!signe(x)) return 0; + n = itos_or_0(x); + if (!n) pari_err_OVERFLOW("t_INT-->long assignment"); - return (s>0) ? u : -u; + return n; } /* as itos, but return 0 if too large. Cf is_bigint */ INLINE long itos_or_0(GEN x) { - long n; - if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0; - return signe(x) > 0? n: -n; + pari_ulong u; + + if (lgefint(x) != 3) return 0; + u = x[2]; + if (signe(x) >= 0) + { + if (u < HIGHBIT) return u; + } + else + { + if (u <= HIGHBIT) return -u; + } + return 0; } INLINE ulong itou(GEN x) diff --git a/src/language/es.c b/src/language/es.c index 5da0e5f..66e6931 100644 --- a/src/language/es.c +++ b/src/language/es.c @@ -2025,7 +2025,7 @@ static void str_long(outString *S, long e) { if (e >= 0) str_ulong(S, (ulong)e); - else { str_putc(S, '-'); str_ulong(S, (ulong)(-e)); } + else { str_putc(S, '-'); str_ulong(S, -(ulong)e); } } static void diff --git a/src/test/32/arith b/src/test/32/arith index 86a8892..64364da 100644 --- a/src/test/32/arith +++ b/src/test/32/arith @@ -1,3 +1,4 @@ 0 4162330905307 +Vecsmall([-2147483648]) Total time spent: 4 diff --git a/src/test/in/arith b/src/test/in/arith index 7af4539..b7f5562 100644 --- a/src/test/in/arith +++ b/src/test/in/arith @@ -2,3 +2,4 @@ issquarefree(0) \\#1412 core(4*10^15+27) +Vecsmall([-2^31]) -- 2.0.5