First the problem.

Z ==> Integer
SI ==> SingleInteger
p:=prevPrime((max()$SI)::Z)$IntegerPrimesPackage(Z)
F ==> PrimeField p
FZ ==> SUP F
f: FZ := monomial(1, 2)$FZ - 2
factor(f)

If running this in a session one ends up with a nasty

(6) -> f: FZ := monomial(1, 2)$FZ - 2
   Compiling function G387 with type Integer -> Boolean
   Compiling function G389 with type NonNegativeInteger -> Boolean

         2
   (6)  ?  + 4611686018427387845
            Type:
SparseUnivariatePolynomial(PrimeField(4611686018427387847))
(7) -> factor(f)

   >> System error:
   The value
  4684986446884335550
is not of type
  FIXNUM


That's probably not a very big surprise when looking at the special
implementation of a finite field for a prime that is just a bit smaller
than the maximum size of a SingleInteger.

However, of course, that shouldn't happen.

I first thought that the multiplication in PrimeField is problematic,
but no, it works fine. The problem is addmod $ SingleInteger.
See session below.

The documentation for addmod of SingleInteger is inherited from
IntegerNumberSystem.

addmod: (%, %, %) -> %
    addmod(a, b, p), 0<=a, b<p>1, means a+b mod p.

Well, one might probably expect that there are problems if the domain
has only the size of a lisp fixnum. But that's certainly implementation
dependent. And seemingly mulmod works just fine for these border cases.

Although, I would somehow like that the ++ docstring for addmod $
SingleInteger would mention the restriction that not only a<p, b<p, but
also a+b<=max(), I can live with the implicit restriction, that a
programmer has to take care in the SingleInteger case.

However, there is a real bug that results from this restriction and that
is in IntegerMod(p)

It says

  if p <= convert(max()$SingleInteger)@Integer then
    Rep := SingleInteger
    q := p::SingleInteger
    ...
  else
    Rep := Integer
    ...

Of course it should rather say:

  if p <= convert(shift(max()$SingleInteger, -1))@Integer then

Bugfix is attached.
Can I commit?

Ralf


(1) -> I ==> SingleInteger
(2) -> p: I := max()$I -123456

   (2)  4611686018427264447
                                Type: SingleInteger
(3) -> a: I := p - 1

   (3)  4611686018427264446
                                Type: SingleInteger
(4) -> b: I := shift(a, -1)+100

   (4)  2305843009213632323
                                Type: SingleInteger
(5) -> a + a

   >> System error:
   The value
  9223372036854528892
is not of type
  FIXNUM

(5) -> b + b

   (5)  4611686018427264646
                                Type: SingleInteger
(6) -> addmod(a, a, p)

   >> System error:
   The value
  9223372036854528892
is not of type
  FIXNUM
(6) -> addmod(b, b, p)

   (6)  199
                                Type: SingleInteger
(7) -> mulmod(a, a, p)

   (7)  1
                                Type: SingleInteger
(8) -> mulmod(a, b, p)

   (8)  2305843009213632124
                                Type: SingleInteger

-- 
You received this message because you are subscribed to the Google Groups 
"FriCAS - computer algebra system" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/fricas-devel/13d47e96-0def-cb1e-aae6-2402b04e8c8b%40hemmecke.org.
From 3eedeffb866913d3cdb4d2150ce3d13380117e69 Mon Sep 17 00:00:00 2001
From: Ralf Hemmecke <[email protected]>
Date: Thu, 12 Dec 2019 22:49:23 +0100
Subject: bugfix representation optimization of IntegerMod

Before the patch, SingleInteger was also choosen as representation
for IntegerMod(p) if p was in the range m/2 < p <= m := max()$SingleInteger.

(1) -> I ==> SingleInteger
(2) -> p: I := max()$I - 123456

   (2)  4611686018427264447
                                Type: SingleInteger
(3) -> a: I := p - 1

   (3)  4611686018427264446
                                Type: SingleInteger
(4) -> a + a

   >> System error:
   The value
  9223372036854528892
is not of type
  FIXNUM

(4) -> addmod(a, a, p)

   >> System error:
   The value
  9223372036854528892
is not of type
  FIXNUM
---
 src/algebra/fmod.spad | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/algebra/fmod.spad b/src/algebra/fmod.spad
index a0490b3a..efc75dad 100644
--- a/src/algebra/fmod.spad
+++ b/src/algebra/fmod.spad
@@ -17,7 +17,7 @@ IntegerMod(p : PositiveInteger):
   lookup x == (zero? x => p; (convert(x)@Integer) :: PositiveInteger)
 
 -- Code is duplicated for the optimizer to kick in.
-  if p <= convert(max()$SingleInteger)@Integer then
+  if p <= convert(shift(max()$SingleInteger, -1))@Integer then
     Rep := SingleInteger
     q := p::SingleInteger
 
-- 
2.17.1

Reply via email to