News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

GCC libquadmath

Started by jj2007, July 21, 2017, 06:42:35 PM

Previous topic - Next topic

jj2007

#15
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 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))
EndOfCode


Output: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.

nidud

#16
deleted

jj2007

#17
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 source. Requires Python 3, the Gnu Scientific Library, 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.

jack

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?

jj2007

#19
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, the QuadMath interface is now implemented. To test it, click in RichMasm File/New Masm source, then QuadMath in the lower left corner.

jj2007

Minor bugfix in version 3 August, details here.

jj2007

A QuadMath array demo:

include \masm32\MasmBasic\MasmBasic.inc     ; download
  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 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
  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