Karim BELABAS on Fri, 3 Oct 2003 11:56:55 +0200 (MEST) |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: qfbprimeform(-3,1)--> stack corruption |
On Thu, 2 Oct 2003, Bill Allombert wrote: > ? qfbprimeform(-3,1) > %1 = Qfb(1, 1, 33554435) > > This looks like a stack corruption do to an abuse of setsigne(y[3],1). Actually data corruption. gzero's sign was set to 1 [ and gzero is not part of the stack ] > Unfortunately, there is no warranty that a PARI function return a value > on the stack rather than gzero or gun. If we can restrain ourself to use > such hack, we should write a macro that do it correctly. I agree with the general comment. Although I don't see how to write a general macro which would not compute a possibly unnecessary signe(), as in your patch in fact. Here is a(n ever so slightly) more efficient patch, which saves a few bitmask operations [ committed to CVS ]. This original formula is av = avma; y[3] = lpileupto(av, shifti(subsi(1, D), -2)); which is wasteful since computing 1 - D, and copying the result (gerepileupto) is unnecessary when D is even, making the routine more than twice slower than it should be in half the cases. I made a mistake when "optimizing" this. Karim. Index: src/basemath/arith2.c =================================================================== RCS file: /home/megrez/cvsroot/pari/src/basemath/arith2.c,v retrieving revision 1.73 diff -u -w -r1.73 arith2.c --- src/basemath/arith2.c 2003/09/08 08:20:58 1.73 +++ src/basemath/arith2.c 2003/10/03 09:44:55 @@ -1669,22 +1669,25 @@ GEN y = cgetg(4,t_QFI); long isodd; - if (typ(D) != t_INT || signe(D) >= 0) err(typeer,"real_unit_form_by_disc"); - switch(4 - mod4(D)) + if (typ(D) != t_INT || signe(D) >= 0) err(typeer,"imag_unit_form_by_disc"); + switch(mod4(D)) { - case 2: - case 3: err(funder2,"imag_unit_form_by_disc"); + case 0: isodd = 0; break; + case 3: isodd = 1; break; + default: err(funder2,"imag_unit_form_by_disc"); + return NULL; /* not reached */ } - y[1] = un; isodd = mpodd(D); + y[1] = un; y[2] = isodd? un: zero; - /* y[3] = (1-D) / 4 or -D / 4, whichever is an integer */ - y[3] = lshifti(D,-2); setsigne(y[3],1); + /* upon return, y[3] = (1-D) / 4 or -D / 4, whichever is an integer */ + y[3] = lshifti(D,-2); if (isodd) { pari_sp av = avma; - y[3] = lpileuptoint(av, addis((GEN)y[3],1)); + y[3] = lpileuptoint(av, addis((GEN)y[3],-1)); } - return y; + /* at this point y[3] < 0 */ + setsigne(y[3], 1); return y; } GEN -- Karim Belabas Tel: (+33) (0)1 69 15 57 48 Dép. de Mathématiques, Bât. 425 Fax: (+33) (0)1 69 15 60 19 Université Paris-Sud http://www.math.u-psud.fr/~belabas/ F-91405 Orsay (France) http://www.parigp-home.de/ [PARI/GP]