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
