This bug report concerns the C++ interface of
GMP versions 6.x.x, 5.1 and probably also others before.
It contains an attached test program, two output files from
the test program, an error description, a suggested patch and
link to an old related bug report from 2009 (the later only for information).

The issue is shown by the attached test program. The test program does
not take any arguments. It computes the
and prints in 2+2 ways (cout/general ofstream and gpm_printf/gpm_fprintf)
(as mpf_class) the double powers: 2^(2^i) for i=0,...,39.
It also produces two (simple and short) output files, also attached to this 
mail.

When i is larger than 32 (i.e. exponent larger than int) cout and ofstream show
wrong exponents (eventually with negative sign) while the gpm_printf
output is correct. This is related to the fact that the gmp float exponent
_mp_exp is of the same size as long (8 bytes; at least on the different linux 
64 bit systems
where I verified this bug) but the print format for the exponent is still of the form 
"%d"
and not "%ld" in the file cxx/osfuns.c.

The problem can be solved by the patch (applied to cxx/osfuns.c):

--- osfuns_orig.cc      2026-05-11 00:43:19.788741882 +0200
+++ osfuns.cc   2026-05-11 00:44:21.706742961 +0200
@@ -60,12 +60,12 @@
 {printf/doprnt.c
   if ((o.flags() & ios::basefield) == ios::hex)
     {
-      p->expfmt = "@%c%02d";
+      p->expfmt = "@%c%02ld";
       p->base = (o.flags() & ios::uppercase ? -16 : 16);
     }
   else
     {
-      p->expfmt = (o.flags() & ios::uppercase ? "E%c%02d" : "e%c%02d");
+      p->expfmt = (o.flags() & ios::uppercase ? "E%c%02ld" : "e%c%02ld");
       if ((o.flags() & ios::basefield) == ios::oct)
         p->base = 8;
       else

This patch is for gmp-6.1.2 but it should be the same for 6.3 (maybe with 
different line numbers)
and other versions. As can be seen it simply replaces %02d by %02ld in three 
places where the format p->expfmt is defined.
I have tested that with this patch the problem is solved (on different 
computers and different gmp version 6.1.2 and 6.3).

By the way, the bug is also related to an old bug report from 2009 for the same 
issue in the
family of gmp_printf functions (which are now okay for this !):

https://gmplib.org/list-archives/gmp-bugs/2009-June/001530.html

where a similar patch for the file printf/doprnt.c was suggested.

In the actual GMP version this file is now correct (using the %ld format for 
the exponent). I suppose this is due to the
old bug report.


Yours sincerely,

Klaus Frahm.

#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
#include <gmpxx.h>
#include <math.h>

int main(){
  // start with an exponent below 2^32
  int i;
  mpf_class x=2;

  // file output
  FILE *fp1;
  ofstream fp;
  fp.open("cout_test.dat");
  fp1=fopen("gmp_printf_test.dat","w");
  for(i=0;i<40;i++){
    // bug: exponents larger than 2^32 are incorrectly printed with C++ streams
    cout << "cout:\t\t 2^(2^" << i << ") \t= " << x << "\n";
    fp << "fp   :\t\t 2^(2^" << i << ") \t= " << x << "\n";
    // correct exponent with gmp_printf type functions
    gmp_printf("gmp_printf:\t 2^(2^%d) \t= %.*Fg\n",i,6,x.get_mpf_t());
    gmp_fprintf(fp1,"gmp_fprintf:\t 2^(2^%d) \t= %.*Fg\n",i,6,x.get_mpf_t());
    x=x*x;
  }
  fp.close();
  fclose(fp1);
}

<<attachment: cout_test.dat>>

<<attachment: gmp_printf_test.dat>>

_______________________________________________
gmp-bugs mailing list
[email protected]
https://gmplib.org/mailman/listinfo/gmp-bugs

Reply via email to