BrianGladman / mpir

Multiple Precision Integers and Rationals
GNU General Public License v3.0
75 stars 36 forks source link

mpz_ui_pow_ui overflow #25

Closed LeslieGreenCEngMIEE closed 2 years ago

LeslieGreenCEngMIEE commented 2 years ago

It is unclear if this is a known MPIR problem on Win64. It seems as if the 3rd function argument in an unsigned long rather than an mpir_ui. Hence it doesn't work as advertised on Win64.

Example code: '

include "stdafx.h"

#include < stdio.h >
#include "D:\MPIR\mpir.h"

 typedef unsigned long long i64;

void main(){

mpz_t fermatNumber1;
mpz_init(fermatNumber1);

mpz_t fermatNumber2;
mpz_init(fermatNumber2);

mpf_t tmp;
mpf_init2(tmp, 128);

for( int F = 30; F < 34; F++ ){

    i64 n = ( 0x01LL << F );            // long long int constant keeps the compiler quiet.
    mpz_ui_pow_ui(fermatNumber1, 2, n);     
    mpz_add_ui(fermatNumber1, fermatNumber1, 1);        // only now is this the Fermat Number

    mpf_set_d(tmp, 2.0);
    mpf_pow_ui(tmp, tmp, n);
    mpz_set_f(fermatNumber2, tmp);
    mpz_add_ui(fermatNumber2, fermatNumber2, 1);        // only now is this the Fermat Number

    printf("\n\nFERMAT NUMBER #%d has ", F);
    i64 digits = mpz_sizeinbase(fermatNumber1, 2);
    printf("\n\t\t(1) digits = %I64d", digits);

    digits = mpz_sizeinbase(fermatNumber2, 2);
    printf("\n\t\t(2) digits = %I64d", digits);
}

printf("\n\n=================== DONE =====================");

mpz_clear(fermatNumber1);   mpz_clear(fermatNumber2);   mpf_clear(tmp);

getchar();

} ` ( Why the GitHub "code" tags are not working correctly on all the code is another mystery!)

Example output:

FERMAT NUMBER 30 has (1) digits = 1073741825 (2) digits = 1073741825

FERMAT NUMBER 31 has (1) digits = 2147483649 (2) digits = 2147483649

FERMAT NUMBER 32 has (1) digits = 2 (2) digits = 4294967297

FERMAT NUMBER 33 has (1) digits = 2 (2) digits = 8589934593

=================== DONE =====================

( I deleted the hash symbols in front of the Fermat Number indexes because they got converted to links )

I don't imagine that it is relevant, but MPIR was compiled as a K8/K10/K102 x64 release DLL for Windows 10, running on an AMD A10-7800 Radeon R7. All the MPIR tests ran correctly. The same DLL/test code also gives the same result on a Xeon E5-1650 v4 processor.

BrianGladman commented 2 years ago

Not a known bug as far as I am aware. I'll look into it.

LeslieGreenCEngMIEE commented 2 years ago

Interestingly, mpz_pow_ui also fails the same test in the same way.

`typedef unsigned long long i64;

void main(){

mpz_t fermatNumber1;
mpz_init(fermatNumber1);

mpz_t two;
mpz_init_set_ui( two, 2);
    ...
for( int F = 30; F < 34; F++ ){

    i64 n = ( 0x01LL << F );            // long long int constant keeps the compiler quiet.

    mpz_pow_ui(fermatNumber1, two, n);          // this one also doesn't work at F32        
    //mpz_ui_pow_ui(fermatNumber1, 2, n);           // doesn't work for F32 or greater
    mpz_add_ui(fermatNumber1, fermatNumber1, 1);        // only now is this the Fermat Number

`

BrianGladman commented 2 years ago

That is not surprising since I wouldn't expect these two functions to be different in their handling of their third argument.

BrianGladman commented 2 years ago

This is a bug, which I have now fixed. Thanks for reporting it.

LeslieGreenCEngMIEE commented 2 years ago

I pulled the changed file and can confirm that both the mpz-pow_ui and the mpz_ui_pow_ui variants are now fixed :-)

Your service is much appreciated.