Jeroen Demeyer on Tue, 23 Sep 2014 15:37:14 +0200

 [PATCH] enable basic arithmetic with infinity

• To: pari-dev <pari-dev@pari.math.u-bordeaux1.fr>
• Subject: [PATCH] enable basic arithmetic with infinity
• From: Jeroen Demeyer <jdemeyer@cage.ugent.be>
• Date: Tue, 23 Sep 2014 15:37:05 +0200
• Delivery-date: Tue, 23 Sep 2014 15:37:14 +0200
• User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0

Dear pari-dev,


The attached patch enables basic arithmetic with t_INFINITY. It adds support for addition, subtraction, multiplication and division of infinity by something (division by infinity is still an error). In all cases, the other operand must be a t_INT, t_REAL or t_FRAC.


This patch (at least for multiplication) is needed to support Denis Simon's 2-descent script which does things like

if (lambda > 2*valuation(x,p),...)


where x can be 0. This gave no problems with PARI-2.7 and earlier because valuation(0,p) returned a very large number.


Cheers,
Jeroen.

commit 56a75c6789284da3a1e0cbaca1254ffcb7c43423
Author: Jeroen Demeyer <jdemeyer@cage.ugent.be>
Date:   Mon Sep 22 17:20:12 2014 +0200

Enable basic arithmetic with t_INFINITY

diff --git a/doc/usersch4.tex b/doc/usersch4.tex
index dde26b6..1592650 100644
--- a/doc/usersch4.tex
+++ b/doc/usersch4.tex
@@ -1501,9 +1501,11 @@ variadic, $0$ else.
This type has a single \typ{INT} component, which is either $1$ or $-1$,
corresponding to $+\infty$ and $-\infty$ respectively.

-\fun{GEN}{mkmoo}{} returns $-\infty$
+\fun{GEN}{mkmoo}{} returns $-\infty$.

-\fun{GEN}{mkoo}{} returns $\infty$
+\fun{GEN}{mkoo}{} returns $\infty$.
+
+\fun{GEN}{mksoo}{long s} returns $\infty$ if $s \geq 0$ and $-\infty$ otherwise.

\fun{long}{inf_get_sign}{GEN x} returns $1$ if $x$ is $+\infty$, and $-1$
if $x$ is $-\infty$.
diff --git a/src/basemath/gen1.c b/src/basemath/gen1.c
index e272eb5..1464e3c 100644
--- a/src/basemath/gen1.c
+++ b/src/basemath/gen1.c
@@ -782,11 +782,16 @@ add_rfrac_scal(GEN y, GEN x)
static GEN
add_scal(GEN y, GEN x, long ty)
{
+  long tx;
switch(ty)
{
+    case t_INFINITY:
+      tx = typ(x);
+      if (tx == t_INT || tx == t_REAL || tx == t_FRAC) return mksoo(inf_get_sign(y));
+      break;
case t_VEC:
if (isintzero(x)) return gcopy(y);
@@ -1015,6 +1020,9 @@ gadd(GEN x, GEN y)
if (lx == 1) return cgetg(1, t_MAT);
if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y);
+    case t_INFINITY:
+      if (inf_get_sign(x) == inf_get_sign(y)) return mksoo(inf_get_sign(x));
+      pari_err_OP("+",x,y);

default: pari_err_TYPE2("+",x,y);
}
@@ -1306,6 +1314,9 @@ gsub(GEN x, GEN y)
return RgM_sub(x,y);
}
case t_RFRAC: case t_SER: break;
+    case t_INFINITY:
+      if (inf_get_sign(x) != inf_get_sign(y)) return mksoo(inf_get_sign(x));
+      pari_err_OP("+",x,y);

default: pari_err_TYPE2("+",x,y);
}
@@ -1370,6 +1381,7 @@ mul_rfrac_scal(GEN n, GEN d, GEN x)
static GEN
mul_scal(GEN y, GEN x, long ty)
{
+  int s;
switch(ty)
{
case t_POL:
@@ -1377,6 +1389,10 @@ mul_scal(GEN y, GEN x, long ty)
return RgX_Rg_mul(y, x);
case t_SER: return mul_ser_scal(y, x);
case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x);
+    case t_INFINITY:
+      s = gsigne(x) * inf_get_sign(y);
+      if (!s) pari_err_OP("*",x,y);
+      return mksoo(s);
case t_QFI: case t_QFR:
if (typ(x) == t_INT && gequal1(x)) return gcopy(y); /* fall through */
}
@@ -1914,6 +1930,7 @@ gmul(GEN x, GEN y)
}
return z;

+    case t_INFINITY: return mksoo(inf_get_sign(x) * inf_get_sign(y));

default:
pari_err_TYPE2("*",x,y);
@@ -2503,6 +2520,7 @@ GEN
gdiv(GEN x, GEN y)
{
long tx = typ(x), ty = typ(y), lx, ly, vx, vy, i;
+  int s;
pari_sp av, tetpil;
GEN z, p1, p2;

@@ -2836,6 +2854,10 @@ gdiv(GEN x, GEN y)
return z;
case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE:
pari_err_TYPE2("/",x,y);
+    case t_INFINITY:
+      s = inf_get_sign(x) * gsigne(y);
+      if (!s) pari_err_INV("/", y);
+      return mksoo(s);
}

vy = gvar(y);
diff --git a/src/basemath/gen2.c b/src/basemath/gen2.c
index 0a94fc4..d85cfda 100644
--- a/src/basemath/gen2.c
+++ b/src/basemath/gen2.c
@@ -1731,7 +1731,7 @@ gneg(GEN x)
case t_VEC: return RgV_neg(x);
case t_COL: return RgC_neg(x);
case t_MAT: return RgM_neg(x);
-    case t_INFINITY: return inf_get_sign(x) == 1? mkmoo(): mkoo();
+    case t_INFINITY: return mksoo(-inf_get_sign(x));
default:
pari_err_TYPE("gneg",x);
return NULL; /* not reached */
@@ -1799,6 +1799,8 @@ gneg_i(GEN x)
gel(y,1) = gneg_i(gel(x,1));
gel(y,2) = gel(x,2); break;

+    case t_INFINITY: return mksoo(-inf_get_sign(x));
+
default:
pari_err_TYPE("gneg_i",x);
return NULL; /* not reached */
index 7e02467..b4ac1c2 100644
@@ -4163,6 +4163,7 @@ INLINE GEN    mkcomplex(GEN x, GEN y);
INLINE GEN    mkerr(long n);
INLINE GEN    mkmoo();
INLINE GEN    mkoo();
+INLINE GEN    mksoo(long s);
INLINE GEN    mkfrac(GEN x, GEN y);
INLINE GEN    mkfraccopy(GEN x, GEN y);
INLINE GEN    mkintmod(GEN x, GEN y);