Michael Stoll on Sun, 19 Apr 1998 21:41:50 +0200

 A few bugs and suggestions

```Here a a few bugs in pari-2.0.7-alpha.

(1) gp> truncate(1/2+O(2))
%1 = 0

Patch (keeping mulii() if possible for the sake of efficiency):
*** gen3.c.orig Sun Apr 19 15:33:15 1998
--- gen3.c      Sun Apr 19 20:55:47 1998
***************
*** 1699,1703 ****
gtrunc(GEN x)
{
!   long tx=typ(x),av,tetpil,i;
GEN y;

--- 1699,1703 ----
gtrunc(GEN x)
{
!   long tx=typ(x),av,tetpil,i,v;
GEN y;

***************
*** 1715,1720 ****
if (!signe(x[4])) return gzero;
!       av=avma; y=gpuigs((GEN)x[2],valp(x)); tetpil=avma;
!       return gerepile(av,tetpil, mulii(y,(GEN)x[4]));

case t_RFRAC: case t_RFRACN:
--- 1715,1731 ----
if (!signe(x[4])) return gzero;
!       av=avma; v=valp(x);
!       if (v>=0) /* p^v is an integer */
!       {
!         y=gpuigs((GEN)x[2],v); tetpil=avma;
!         return gerepile(av,tetpil,mulii(y,(GEN)x[4]));
!       }
!       else /* result is fraction x[4]/p^(-v);
!               should already be in lowest terms */
!       { y=cgetg(3,t_FRAC);
!         y[1]=lcopy((GEN)x[4]);
!         y[2]=lpuigs((GEN)x[2],-v); tetpil=avma;
!         return gerepile(av,tetpil,y);
!       }

case t_RFRAC: case t_RFRACN:

(2) gp> polresultant(u+v,u-v,v)
%4 = x + u
but
gp> polresultant(u+v,u-v)
%5 = 2*u

Patch (this was an easy one, although it took me some time to find it):
*** polarit2.c.orig     Sun Apr 19 15:57:16 1998
--- polarit2.c  Sun Apr 19 20:30:05 1998
***************
*** 1725,1731 ****
if (v >= 0)
{
x = fix_pol(x,v, &m);
!     y = fix_pol(x,v, &m);
}
switch(flag)
{
--- 1725,1731 ----
if (v >= 0)
{
x = fix_pol(x,v, &m);
!     y = fix_pol(y,v, &m);
}
switch(flag)
{

Now for the suggestions:

(3) Is there anybody out there who hasn't yet cursed gp while writing
statements like
subst(subst(subst(subst(......subst(expr,v1,e1),v2,e2),.....)  ?
It would be much nicer to simply write
subst(expr,[v1,v2,....],[e1,e2,....])
(with the substitution done in parallel, of course!). This will require
some rewriting of gsubst(). The best thing to do probably is to order
the variables v1,v2,.... first.

(4) Consider the following gp code.
expr = v^2+v+1;
test1(a  /* local: */ ,v,u) = v = a^2; u = eval(expr); test2(u)
test2(u) = subst(expr,v,u)
(Admittedly, this doesn't make much sense, but you get the idea...)
Now
gp> test1(1)
***   variable name expected: subst(expr,v,u)
^---
Why? This is because v is bound by test1 (this would even happen if
we don't use v in test1 at all) and this binding is in effect when
test2 is called. This is the kind of non-local effect (you can't detect
it from looking at the definition of test2) that is a typical problem of
dynamically bound variables.
Now it would be fine to have lexically scoped variables in gp, but this
is quite obviously not within reach. Instead I suggest to introduce
a construct that takes a variable name and returns the corresponding
variable unevaluated. I suggest the name quote for it, and 'a would be
a convenient shorthand for quote(a) (ever heard of Lisp?). Note that
this can't be a function, but belongs with for,if,vector and friends.

(5)   gp> valuation(0,5)
***   zero argument in gval.
This might be OK (but is a nuisance quite often), but the following is
not.
gp> valuation([1,2,3,0],5)
***   zero argument in gval.
(Strangely enough, it does work for polynomials that contain zero coeffs.)
I suggest replacing line 667 in gen2.c
if (isexactzero(x)) err(talker,"zero argument in gval");
with
if (isexactzero(x)) reteurn VERYBIGINT;
(compare padicprec). If there are objections, then I'd suggest
introducing a flag to switch between the two behaviours.

That much for today --
Michael
```

• Follow-Ups:
• Re: quote
• From: Michael Stoll <Michael_Stoll@math.uni-bonn.de>