| 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