Anybody able to compile that without errors?
#include <conio.h>
#include <C:\MinGW\lib\gcc\mingw32\4.8.1\include\quadmath.h>
// OPT_Linker C:\MinGW\lib\gcc\mingw32\4.8.1\libquadmath.a
int main ()
{
__float128 r;
r = strtoflt128("1.2345678", NULL); // undefined reference to `strtoflt128'
r = 123.456; // OK
_getch();
}
See How to output 128 bits to the screen? (http://masm32.com/board/index.php?topic=6407.0)
Hi Johen,
I was able to compile this on Ubuntu 14.04 :
#include <stdio.h>
#include <quadmath.h>
// gcc ./quadmath.c -o quadmath -lquadmath
int main ()
{
__float128 r;
r = strtoflt128("1.2345678", NULL); // undefined reference to `strtoflt128'
r = 123.456; // OK
getchar();
}
Thanks :icon14:
No luck on Windows, though.
#include <stdio.h>
#include <quadmath.h>
// gcc ./quadmath.c -o quadmath -lquadmath
// gcc quadmath.c -o quadmath -Wl,-Bstatic -lquadmath
int main ()
{
__float128 r;
char buf[128];
r = strtoflt128("1.2345678", NULL); // undefined reference to `strtoflt128'
r = 123.456; // OK
// quadmath_snprintf (buf, sizeof buf, "%Qa", r);
quadmath_snprintf (buf, sizeof buf, "%Qf\n", r);
printf(buf);
getchar();
return 0;
}
123.456000
Thanks, Tim, and congrats :icon_mrgreen:
So are these your linker options?
gcc quadmath.c -o quadmath -Wl,-Bstatic -lquadmath
My results:
C:\TDM-GCC-32\bin\gcc.exe -Wl,-Bstatic -lquadmath -o tmp.exe "Tmp.cpp"
C:\Users\Jochen\AppData\Local\Temp\cceeec7X.o:Tmp.cpp:(.text+0x29): undefined reference to `strtoflt128'
C:\Users\Jochen\AppData\Local\Temp\cceeec7X.o:Tmp.cpp:(.text+0xc9): undefined reference to `quadmath_snprintf'
C:/TDM-GCC-32/bin/../lib/gcc/mingw32/4.9.2/../../../../mingw32/bin/ld.exe: C:\Users\Jochen\AppData\Local\Temp\cceeec7X.o: bad reloc address 0x7 in section `.text$getchar[_getchar]'
C:/TDM-GCC-32/bin/../lib/gcc/mingw32/4.9.2/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
If I remove the comma (-Wl -Bstatic), it tells me unrecognized command line option '-Wl', so I assume the comma has a meaning.
My installation is less than three years old. Most of the time C/C++ code compiles and runs fine, but this one gives me the creeps :(
C:\MinGW\mingw32\lib\gcc\mingw32\4.8.1\libquadmath.a 570236 bytes, 5.10.2013
C:\MinGW\mingw32\lib\gcc\mingw32\4.8.1\include\quadmath.h 9030 bytes, 5.10.2013
P.S.: I love passing hours and hours on the Internet watching how others despair :t
But in the end, own trial and error may advance humanity more quickly :biggrin:#include <stdio.h>
#include <quadmath.h>
// gcc ./quadmath.c -o quadmath -lquadmath
// gcc quadmath.c -o quadmath
// OxPT_Linker -Wl,-Bstatic -lquadmath
// OxPT_Linker -Wl,-Bdynamic -lquadmath
// OxPT_Linker -Wl,-Bstatic "C:\MinGW\mingw32\lib\gcc\mingw32\4.8.1\libquadmath.a"
// OxPT_Linker -Wl,-Bdynamic C:\TDM-GCC-32\bin\libquadmath-0.dll
// OPT_Linker C:\TDM-GCC-32\bin\libquadmath-0.dll ; HEY, THIS ONE WORKS!!!!
int main ()
{
__float128 r;
char buf[128];
for (int i=0;i<128;i++) buf[i]=0;
// __asm("int $3");
r = strtoflt128("1.2345678", NULL); // undefined reference to `strtoflt128'
// __asm("nop");
// r = 123.456; // OK
quadmath_snprintf (buf, sizeof buf, "%Qa", r);
quadmath_snprintf (buf, sizeof buf, "%Qf\n", r);
printf("Buffer: [%s]", buf);
getchar();
return 0;
}
Output: Buffer: [0x1.3c0ca2a5b1d5d0818d3359c99ff2p+0]
Not yet the expected result, but since I've seen some similar results in desperate posts on the web (e.g. That code produced -3.8518598887744717061119558851698546e-34 error on my box (http://grumpyoldprogrammer.blogspot.it/2015/04/gcc-quad-precision-math-library-example.html)), it can only be a question of weeks until I find the magic trick :icon_mrgreen:
The order of modules and libraries must match the dependency order:
Quote from: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html-l library
[...]
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, 'foo.o -lz bar.o' searches library 'z' after file foo.o but before bar.o. If bar.o refers to functions in 'z', those functions may not be loaded.
Conclusion: put -lquadmath to the end.
Also note that gcc use the file extension to get the language and c++ is maybe not what you want in general.
Miracles happen :greenclp:
#include <stdio.h> // HEY, THIS ONE WORKS!!!!
#include <quadmath.h> // OPT_Linker C:\TDM-GCC-32\bin\libquadmath-0.dll
int main ()
{
char buf[128];
__float128 r = strtoflt128("1234567890.123456789012345678901234567890", NULL);
quadmath_snprintf (buf, sizeof buf, "%#*.40Qe", 30, r);
printf("expected:\t[1.2345678901234567890123456789012345678901e+09]\n", buf);
printf("result: \t[%s]\n", buf);
getchar();
return 0;
}
// Output
// expected: [1.2345678901234567890123456789012345678901e+09]
// result: [1.2345678901234567890123456789012345331810e+09]
@qWord: Thanks, your suggestion to put -lquadmath as last option works, too :t
Work in progress:
PrintLine "Two numbers: ", CrLf$, Quad$(numSmall), " and ", CrLf$, Quad$(numBig)
Inkey Quad$(QuadMath(fminq, numSmall, numBig)), " is the smaller one"
Two numbers:
1.2345678901234567890294135408477e+40 and
1.2345678901234567891474727029195e+40
1.2345678901234567890294135408477e+40 is the smaller one
The interface works, but there is a big problem: simple arithmetics like adding and multiplying numbers :(
I found two symbols that have add in it: ___quadmath_mpn_addmul_1 and ___quadmath_mpn_add_n
for subtract: ___quadmath_mpn_submul_1 and ___quadmath_mpn_sub_n
for divide: ___quadmath_mpn_divrem
for multiply: ___quadmath_mpn_mul_1, ___quadmath_mpn_impn_mul_n_basecase, ___quadmath_mpn_impn_mul_n and ___quadmath_mpn_mul
Thanks, Jack :t
There are quite a number of them:__quadmath_do_pad
__quadmath_fpioconst_pow10
__quadmath_isinf_nsq
__quadmath_kernel_cosq
__quadmath_kernel_sincosq
__quadmath_kernel_sinq
__quadmath_mpn_add_n
__quadmath_mpn_addmul_1
__quadmath_mpn_cmp
__quadmath_mpn_construct_float128
__quadmath_mpn_divrem
__quadmath_mpn_extract_flt128
__quadmath_mpn_impn_mul_n
__quadmath_mpn_impn_mul_n_basecase
__quadmath_mpn_lshift
__quadmath_mpn_mul
__quadmath_mpn_mul_1
__quadmath_mpn_rshift
__quadmath_mpn_sub_n
__quadmath_mpn_submul_1
__quadmath_printf_fp
__quadmath_printf_fphex
__quadmath_rem_pio2q
__quadmath_tens
__quadmath_tens_in_limb
__quadmath_x2y2m1q
Problem is that they are not documented. There is a doc on Low-level Functions (http://web.mit.edu/gnu/doc/html/gmp_6.html), but it concerns general GCC functions.
It would be great if we could decipher them, i.e. find out which paras they expect, and how they are passed. So far I have been successful with quite a number of the documented functions, and added conversion REAL10 <---> REAL16, printing etc:
include \masm32\MasmBasic\MasmBasic.inc
SetGlobals REAL16:quadPI
Init quad
PrintLine "real PI:", Tb$, "3.14159265358979323846264338327950"
MovVal quadPI, "3.14159265358979323846264338327950" ; string to REAL16
PrintLine "quadPI= ", Tb$, Quad$(quadPI)
FpuPush quadPI ; REAL16 -> REAL10
PrintLine "FpuPush=", Tb$, Str$(ST(0)v)
fldpi ; same with built-in FPU opcode
Inkey "fldpi =", Tb$, Str$(ST(0)v)
EndOfCode
Output:
real PI: 3.14159265358979323846264338327950
quadPI= 3.14159265358979323846264338327950e+00
FpuPush= 3.141592653589793238
fldpi = 3.141592653589793238
When the package is ready, I'll update the MovVal (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1203) and FpuPush (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1189) documentation asap.
The __float128-type is build-in thus the common operators can be used. Write your own functions to make the basic arithmetic available as lib.
jj2007, may I suggest you try the C explorer at https://godbolt.org
choose gcc as the compiler with compiler option -O3 and paste the following C code
#include <quadmath.h>
#include <stdlib.h>
#include <stdio.h>
int main ()
{
__float128 a, b, r;
char buf[128];
printf("enter first 128-bit float ");
scanf("%s", buf);
a = strtoflt128 (buf, NULL);
printf("enter second 128-bit float ");
scanf("%s", buf);
b = strtoflt128 (buf, NULL);
r=a+b;
quadmath_snprintf (buf, sizeof buf, "%+-#46.*Qe", r);
return 0;
}
you will see that it calls __addtf3, which is part of libgcc, see https://github.com/gcc-mirror/gcc/tree/master/libgcc/soft-fp
Quote from: jack on July 30, 2017, 10:17:02 PMyou will see that it calls __addtf3, which is part of libgcc, see https://github.com/gcc-mirror/gcc/tree/master/libgcc/soft-fp
Yep, that does the trick, thanks a lot :t
@qword: "Write your own functions"?
deleted
e.g.
void myAdd(__float128 *const r, __float128 const *const a, __float128 const *const b) { *r = *a + *b; }
Has the advantage to rely only on GCC's public interface.
Quote from: nidud on July 31, 2017, 02:30:42 AM
The FPU handles up to REAL10.
Floats above must be emulated.
Compliments, you read the manual :t
Quote from: qWord on July 31, 2017, 03:41:02 AMvoid myAdd(__float128 *const r, __float128 const *const a, __float128 const *const b) { *r = *a + *b; }
Good. Now the same from assembler, and we can have some fun :biggrin:
Attached the beta version, MasmBasic version 1 August (http://masm32.com/board/index.php?topic=94.0) is needed to build this example:
include \masm32\MasmBasic\MasmBasic.inc
SetGlobals REAL16 quadPI, Num1, Num2
Init quad
PrintLine "real PI:", Tb$, "3.14159265358979323846264338327950"
MovVal quadPI, "3.1415926535897932384626433832795028841971" ; string to REAL16
PrintLine "quadPI= ", Tb$, Quad$(quadPI)
FpuPush quadPI ; REAL16 -> REAL10
PrintLine Str$("FpuPush=\t%Jf", ST(0)v)
fldpi ; same with built-in FPU opcode
PrintLine Str$("fldpi =\t%Jf", ST(0)v)
MovVal Num1, "1.234567890123456789012345678901234567890" ; string to REAL16
MovVal Num2, "2.222222222222222222222222222222222222222" ; string to REAL16
PrintLine "Num1=", Tb$, Tb$, Quad$(Num1)
PrintLine "Num2=", Tb$, Tb$, Quad$(Num2)
PrintLine "Num1+Num2=", Tb$, Quad$(QuadMath(__addtf3, Num1, Num2))
PrintLine "Num1-Num2=", Tb$, Quad$(QuadMath(__subtf3, Num1, Num2))
PrintLine "Num1*Num2=", Tb$, Quad$(QuadMath(__multf3, Num1, Num2))
Inkey "Num1/Num2=", Tb$, Quad$(QuadMath(__divtf3, Num1, Num2))
EndOfCodeOutput:
real PI: 3.14159265358979323846264338327950
quadPI= 3.14159265358979323846264338327950e+00
FpuPush= 3.141592653589793238
fldpi = 3.141592653589793238
Num1= 1.23456789012345678901234567890123e+00
Num2= 2.22222222222222222222222222222222e+00
Num1+Num2= 3.45679011234567901123456790112346e+00
Num1-Num2= -9.87654332098765433209876543320988e-01
Num1*Num2= 2.74348420027434842002743484200274e+00
Num1/Num2= 5.55555550555555555055555555505556e-01
As mentioned earlier, it needs C:\TDM-GCC-32\bin\libquadmath-0.dll
If your GCC is elsewhere, use ...
QuadLib$ equ <yourpath\bin\libquadmath-0>
GccLib$ equ <yourpath\bin\libgcc_s_dw2-1>
... shortly before Init (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1009).
deleted
Quote from: nidud on July 31, 2017, 05:46:17 AMif you write the emulation yourself you don't need to use the GCC-libs.
Sure, but why reinvent the wheel if GCC has already 100 REAL16 functions? Many people have a GCC installation anyway, and it works just fine. Why should an assembler programmer
not use the wealth of libraries that are the only real advantage of C/C++?
I attach an update of the Printing a sinus via the FPU, the CRT, the GSL, and Python (http://masm32.com/board/index.php?topic=94.msg43801#msg43801) source. Requires Python 3, the Gnu Scientific Library (http://gnuwin32.sourceforge.net/packages/gsl.htm), and GCC QuadMath.
Printing the sinus of 3.0 in various languages:
Sinus(3)= 0.1411200080598672 Python 3.4.3
Sinus(3)= 0.1411200080598672135 GSL, global var
Sinus(3)= 0.1411200080598672135 GSL, immediate
Sinus(3)= 0.1411200080598672135 CRT, global var
Sinus(3)= 0.1411200080598672135 CRT, immediate
Sinus(3)= 0.1411200080598672221 Assembler/Fpu
Sinus(3)= 0.14112000805986722210074480280811 QuadMath
Exact: 0.1411200080598672221007448028081103... Wolfram Alpha
EDIT:Quote from: nidud on July 31, 2017, 05:46:17 AMWhat qword was hinting (I assume) was that if you write the emulation yourself you don't need to use the GCC-libs.
Reading his post again, it seems he means we could write a DLL or LIB in GCC that exports the 128 bit arithmetic functions. Not a bad idea, actually:
+: no GCC installation needed
-: but the DLL or LIB would bloat the MB package beyond this forum's 512k limit ;)
EDIT(2): On Win10, Python may not run properly. If it hangs, press Ctrl C.
hello jj2007
I am trying to use the function __addtf3 in FreeBasic but the result is wrong, how do you call the function in asm?
Put an int 3 and launch olly. Check what happens in qmP proc. Can't do more now, no access to my computer.
In version 1 August 17 of MasmBasic (http://masm32.com/board/index.php?topic=94.0), the QuadMath interface is now implemented. To test it, click in RichMasm File/New Masm source, then QuadMath in the lower left corner.
Minor bugfix in version 3 August, details here (http://masm32.com/board/index.php?topic=94.msg69033#msg69033).
A QuadMath array demo:
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
Init quad
PrintCpu 0
NanoTimer()
Dim MyQ() As REAL16 ; ** demo showing how to use a float128 array **
Loops=1000000 ; create one Million elements
For_ ecx=0 To Loops-1
push Rand64() ; returns eax
push edx ; and edx
movlps xmm0, qword ptr stack
void Str$("%Jf", xmm0) ; assign a random value
; deb 10, "ct", ecx, $eax ; activate to debug the first 10 iterations
MovVal MyQ(ecx), eax ; string to quad
add esp, QWORD ; correct the stack
; no good: MovVal MyQ(ecx), Str$("%Jf", number) ; chokes
Next
Print Str$("%i ms for creating one Million array elements\n", NanoTimer(ms))
; not possible: ArraySort (http://www.webalice.it/jj2006/MasmBasicQuickReference.htmMb1176) MyQ() sorry but sorting quads is not implemented!
PrintLine "digits", Tb$, "1.234567890123456789012"
For_ ecx=0 To 9
PrintLine Str$("%i\t", ecx), Quad$(MyQ(ecx), "%*.32Qg", 24) ; see doc on format (https://gcc.gnu.org/onlinedocs/gcc-6.3.0/libquadmath/quadmath_005fsnprintf.htmlquadmath_005fsnprintf)
Next
Inkey "-- hit any key --"
EndOfCode
Output:Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
657 ms for creating one Million array elements
digits 1.234567890123456789012
0 8334395503510177650.000
1 1329069443230085730.000
2 2521605505399485735.000
3 -2513648910981773731.00
4 -6348034448820748366.00
5 -3307815091408750516.00
6 4066175164584430395.000
7 -3922227355712582401.00
8 428641309453789440.0000
9 -8910786329316853516.00
Instead of fumbling the stack, this works, too:
void Rand64() ; create a random value
void Str$("%Jf", edx::eax) ; convert to a string
MovVal MyQ(ecx), eax ; convert to a float128