added some operator overloading to make it easier to use.
have split the file so the forum won't choke.
part 1 of 3
"quad.bi"
Code: Select all
'MODULE quadruple_precision
'
' This version is for Compaq Fortran, Lahey/Fujitsu LF95 and
' Absoft ProFortran 6.0.
' N.B. The -o0 option (no optimization) must be used with LF95.
'
' N.B. This is quadruple precision implemented in SOFTWARE, hence it is SLOW.
' This package has NOT been tested with other Fortran 90 compilers.
' The operations +-*/ & sqrt will probably work correctly with other compilers
' for PCs. Functions and routines which initialize quadruple-precision
' constants, particularly the trigonometric and exponential functions will
' only work if the compiler initializes double-precision constants from
' decimal code in exactly the same way as the Lahey compilers.
' The basic algorithms come from:
' Linnainmma, S. Software for doubled-precision floating-point computations,
' ACM Trans, Math. Software, vol. 7, pp.272-283, 1981.
' Programmer : Alan Miller
' e-mail: amiller @ bigpond.net.au URL: http://users.bigpond.net.au/amiller
' Latest revision - 18 September 2002
' 4 Aug 97. Added new algorithm for exponential. Takes half the time of the
' previous Taylor series, but errors 2.5 times larger. The old
' exponential is included here under the name exp_taylor for anyone
' who needs the extra accuracy. To use it instead of the new
' algorithm, change the module procedure name in INTERFACE exp from
' longexp to exp_taylor.
' 5 Aug 97. Found way to reduce cancellation errors in yesterday's algorithm
' for the exponential. Removed exp_taylor.
' 18 Aug 97. Added table of quadruple-precision constants.
' 8 Sept 97. Added str_quad which reads a character string and converts it to
' quadruple-precision form.
' 15 Oct 97. Added quad_str which takes a quadruple-precision value and outputs
' a character string containing its decimal value to 30 significant
' digits.
' Added overlays to the ** operator for quadruple-precision values.
' 15 Jan 98. Added ATAN2.
' 19 Jan 98. Added <, <=, ==, >= and >.
' 27 Dec 98. Added quad/real, quad/integer, integer/quad, real/quad, dp/quad,
' int+quad, real+quad, dp+quad, int-quad, real-quad, dp-quad,
' SUM, DOT_PRODUCT & MATMUL.
' 29 Dec 98. Correction to routine string_quad for strings of < 5 characters.
' 10 May 99. Added EPSILON for quad type.
' 5 Oct 99. log10e corrected.
' 15 Oct 99. Corrected function quad_pow_int.
' 18 Oct 99. Rewrote quad_pow_int to use the binary power method.
' 11 Nov 99. Added overlaying of assignments, e.g. quad = int, etc.
' 21 Jan 00. Added inreface for EPSILON.
' 17 Feb 02. Corrected ACOS & ASIN for arguments close to +1 or -1.
' 18 Feb 02. Further improvement to ACOS.
' 18 Sep 02. Added reference to Linnainmaa in comments at beginning.
#include "string.bi"
namespace quad_precision
'dp = 8 = double
Dim Shared As Integer nbits = 53
Dim Shared As Double constant = 134217729.0 '=2^(nbits - nbits\2) + 1
Dim Shared As Double zero = 0.0
Dim Shared As Double one = 1.0
Type quad
As Double hi, lo
Declare constructor ( Byref rhs As quad )
Declare constructor ( byref rhs As Integer = 0 )
Declare constructor ( byref rhs As Long = 0 )
Declare constructor ( byref rhs As LongInt = 0 )
Declare constructor ( byref rhs As UInteger = 0 )
Declare constructor ( byref rhs As ULong = 0 )
Declare constructor ( byref rhs As ULongInt = 0 )
Declare constructor ( byref rhs As Single )
Declare constructor ( byref rhs As Double )
Declare constructor ( Byref rhs As String ="0" )
Declare Operator Let( Byref rhs As quad )
Declare Operator Let( Byref rhs As Integer )
Declare Operator Let( Byref rhs As Long )
Declare Operator Let( Byref rhs As Longint )
Declare Operator Let( Byref rhs As Uinteger )
Declare Operator Let( Byref rhs As ULong )
Declare Operator Let( Byref rhs As Ulongint )
Declare Operator Let( Byref rhs As Single )
Declare Operator Let( Byref rhs As Double )
Declare Operator Let( Byref rhs As String )
'' implicit step versions
Declare Operator For ( )
Declare Operator Step( )
Declare Operator Next( Byref end_cond As quad ) As Integer
'' explicit step versions
Declare Operator For ( Byref step_var As quad )
Declare Operator Step( Byref step_var As quad )
Declare Operator Next( Byref end_cond As quad, Byref step_var As quad ) As Integer
Declare Operator += ( Byref rhs As quad )
Declare Operator += ( Byref rhs As Double )
Declare Operator += ( Byref rhs As Integer )
Declare Operator += ( Byref rhs As String )
Declare Operator -= ( Byref rhs As quad )
Declare Operator -= ( Byref rhs As Double )
Declare Operator -= ( Byref rhs As Integer )
Declare Operator -= ( Byref rhs As String )
Declare Operator *= ( Byref rhs As quad )
Declare Operator *= ( Byref rhs As Double )
Declare Operator *= ( Byref rhs As Integer )
Declare Operator *= ( Byref rhs As String )
Declare Operator /= ( Byref rhs As quad )
Declare Operator /= ( Byref rhs As Double )
Declare Operator /= ( Byref rhs As Integer )
Declare Operator /= ( Byref rhs As String )
Declare Operator ^= ( Byref rhs As quad )
Declare Operator ^= ( Byref rhs As Double )
Declare Operator ^= ( Byref rhs As Integer )
Declare Operator ^= ( Byref rhs As String )
Declare Operator cast( ) As Integer
Declare Operator cast( ) As Long
Declare Operator cast( ) As Longint
Declare Operator cast( ) As Uinteger
Declare Operator cast( ) As ULong
Declare Operator cast( ) As Ulongint
Declare Operator cast( ) As Single
Declare Operator cast( ) As Double
Declare Operator cast( ) As String
End Type
Type quad_rm
As Integer n
As quad rm
end type
Declare Function longadd(Byref a As quad, Byref c As quad) As quad
Declare Function string_quad(Byref value As String) As quad
Declare Function quad_string(Byref value As quad) As String
Function cquad Overload(Byref a As Double, Byref b As Double) As quad
Dim As quad c
c.hi=a
c.lo=b
Return c
End Function
Dim Shared As quad _
pi = cquad ( 0.3141592653589793D+01, 0.1224646799147353D-15 ), _
piby2 = cquad ( 0.1570796326794897D+01, -.3828568698926950D-15 ), _
piby3 = cquad ( 0.1047197551196598D+01, -.3292527815701405D-15 ), _
piby4 = cquad ( 0.7853981633974484D+00, -.8040613248383182D-16 ), _
piby6 = cquad ( 0.5235987755982990D+00, -.1646263907850702D-15 ), _
twopi = cquad ( 0.6283185307179586D+01, 0.2449293598294707D-15 ), _
ln_pi = cquad ( 0.1144729885849400D+01, 0.2323105560877391D-15 ), _
sqrtpi = cquad ( 0.1772453850905516D+01, -.7666586499825800D-16 ), _
fact_pt5 = cquad ( 0.8862269254527582D+00, -.1493552349616447D-15 ), _
sqrt2pi = cquad ( 0.2506628274631001D+01, -.6273750096546544D-15 ), _
lnsqrt2pi = cquad ( 0.9189385332046728D+00, -.3878294158067242D-16 ), _
one_on2pi = cquad ( 0.1591549430918953D+00, 0.4567181289366658D-16 ), _
two_on_rtpi = cquad ( 0.1128379167095513D+01, -.4287537502368968D-15 ), _
deg2rad = cquad ( 0.1745329251994330D-01, -.3174581724866598D-17 ), _
rad2deg = cquad ( 0.5729577951308232D+02, -.1987849567057628D-14 ), _
ln2 = cquad ( 0.6931471805599454D+00, -.8783183432405266D-16 ), _
ln10 = cquad ( 0.2302585092994046D+01, -.2170756223382249D-15 ), _
log2e = cquad ( 0.1442695040888964D+01, -.6457785410341630D-15 ), _
log10e = cquad ( 0.4342944819032519D+00, -.5552037773430574D-16 ), _
log2_10 = cquad ( 0.3321928094887362D+01, 0.1661617516973592D-15 ), _
log10_2 = cquad ( 0.3010299956639812D+00, -.2803728127785171D-17 ), _
euler = cquad ( 0.5772156649015330D+00, -.1159652176149463D-15 ), _
e = cquad ( 0.2718281828459045D+01, 0.1445646891729250D-15 ), _
sqrt2 = cquad ( 0.1414213562373095D+01, 0.1253716717905022D-15 ), _
sqrt3 = cquad ( 0.1732050807568877D+01, 0.3223954471431004D-15 ), _
sqrt10 = cquad ( 0.3162277660168380D+01, -.6348773795572286D-15 ), _
piby40 = cquad ( 0.7853981633974484E-01, -.1081617080994607E-16 )
Function exactmul2(Byref a As Double, Byref c As Double) As quad 'Result(ac)
' Procedure exactmul2, translated from Pascal, from:
' Linnainmaa, Seppo (1981). Software for doubled-precision floating-point
' computations. ACM Trans. on Math. Software (TOMS), 7, 272-283.
' Local variables
Dim As quad ac
Dim As Double a1, a2, c1, c2, t
' t = constant * a
' a1 = (a - t) + t ' Lahey's optimization removes the brackets
' ' and sets a1 = a which defeats the whole point.
' a2 = a - a1
' t = constant * c
' c1 = (c - t) + t
' c2 = c - c1
' ac.hi = a * c
' ac.lo = (((a1 * c1 - ac.hi) + a1 * c2) + c1 * a2) + c2 * a2
Asm
' t = constant * a
movsd xmm0, qword Ptr [constant]
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
movsd qword Ptr [t], xmm0
' a1 = (a - t) + t ! lahey's optimization removes the brackets
' and sets a1 = a which defeats the whole point.
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [t]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [t]
addsd xmm0, xmm1
movsd qword Ptr [a1], xmm0
' a2 = a - a1
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [a1]
subsd xmm0, xmm1
movsd qword Ptr [a2], xmm0
' t = constant * c
movsd xmm0, qword Ptr [constant]
mov eax, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
movsd qword Ptr [t], xmm0
' c1 = (c - t) + t
mov eax, dword Ptr [c]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [t]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [t]
addsd xmm0, xmm1
movsd qword Ptr [c1], xmm0
' c2 = c - c1
mov eax, dword Ptr [c]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [c1]
subsd xmm0, xmm1
movsd qword Ptr [c2], xmm0
' ac.hi = a * c
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
mov eax, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (((a1 * c1 - ac.hi) + a1 * c2) + c1 * a2) + c2 * a2
movsd xmm0, qword Ptr [a1]
movsd xmm1, qword Ptr [c1]
mulsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [a1]
movsd xmm2, qword Ptr [c2]
mulsd xmm1, xmm2
addsd xmm0, xmm1
movsd xmm1, qword Ptr [c1]
movsd xmm2, qword Ptr [a2]
mulsd xmm1, xmm2
addsd xmm0, xmm1
movsd xmm1, qword Ptr [c2]
movsd xmm2, qword Ptr [a2]
mulsd xmm1, xmm2
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0 'ac.lo
End asm
Return ac
End Function 'exactmul2
Function longmul(Byref a As quad, Byref c As quad) As quad
' procedure longmul, translated from pascal, from:
' linnainmaa, seppo (1981). software for doubled-precision floating-point
' computations. acm trans. on math. software (toms), 7, 272-283.
Dim As quad ac, z
' local variables
Dim As Double zz, a1, a2, c1, c2, t
' z = exactmul2(a.hi, c.hi)
asm
' t = constant * a
movsd xmm0, qword Ptr [constant]
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
movsd qword Ptr [t], xmm0
' a1 = (a - t) + t ! lahey's optimization removes the brackets
' and sets a1 = a which defeats the whole point.
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [t]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [t]
addsd xmm0, xmm1
movsd qword Ptr [a1], xmm0
' a2 = a - a1
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [a1]
subsd xmm0, xmm1
movsd qword Ptr [a2], xmm0
' t = constant * c
movsd xmm0, qword Ptr [constant]
mov eax, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
movsd qword Ptr [t], xmm0
' c1 = (c - t) + t
mov eax, dword Ptr [c]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [t]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [t]
addsd xmm0, xmm1
movsd qword Ptr [c1], xmm0
' c2 = c - c1
mov eax, dword Ptr [c]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [c1]
subsd xmm0, xmm1
movsd qword Ptr [c2], xmm0
' ac.hi = a * c
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
mov eax, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (((a1 * c1 - ac.hi) + a1 * c2) + c1 * a2) + c2 * a2
movsd xmm0, qword Ptr [a1]
movsd xmm1, qword Ptr [c1]
mulsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [a1]
movsd xmm2, qword Ptr [c2]
mulsd xmm1, xmm2
addsd xmm0, xmm1
movsd xmm1, qword Ptr [c1]
movsd xmm2, qword Ptr [a2]
mulsd xmm1, xmm2
addsd xmm0, xmm1
movsd xmm1, qword Ptr [c2]
movsd xmm2, qword Ptr [a2]
mulsd xmm1, xmm2
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0 'ac.lo
End asm
z=ac
asm
'zz = ((a.hi + a.lo) * c.lo + a.lo * c.hi) + z.lo
mov eax, dword Ptr [a]
mov edx, dword Ptr [a] 'a
movsd xmm0, qword Ptr [eax] 'a.hi
movsd xmm1, qword Ptr [8+edx] 'a.lo
addsd xmm0, xmm1
mov eax, dword Ptr [c]
movsd xmm1, qword Ptr [8+eax] 'c.lo
mulsd xmm0, xmm1
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax] 'a.lo
mov eax, dword Ptr [c] 'c
movsd xmm2, qword Ptr [eax] 'c.hi
mulsd xmm1, xmm2
addsd xmm0, xmm1
movsd xmm1, qword Ptr [z+8] 'z.lo
addsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
End asm
ac.hi = z.hi + zz
ac.lo = (z.hi - ac.hi) + zz
Return ac
End Function
Function mult_quad_int(Byref a As quad, Byref i As Integer) As quad
' multiply quadruple-precision number (a) by an integer (i).
Dim As quad c = cquad(zero, zero)
Dim As Double di = i
If (i = 1) Then
c = a
Elseif (i = -1) Then
c.hi = -a.hi
c.lo = -a.lo
Else
c = longadd(exactmul2(a.hi, di) , exactmul2(a.lo, di))
End If
Return c
End Function
Function mult_int_quad(Byref i As Integer, Byref a As quad) As quad'Result(c)
' Multiply quadruple-precision number (a) by an Integer (i).
Dim As quad c
If (i = 0) Then
c = cquad(zero, zero)
Elseif (i = 1) Then
c = a
Elseif (i = -1) Then
c.hi = -a.hi
c.lo = -a.lo
Else
c = longadd(exactmul2(a.hi, Cdbl(i)) , exactmul2(a.lo, Cdbl(i)))
End If
Return c
End Function 'mult_int_quad
Function mult_quad_dp(Byref a As quad, Byref b As Double) As quad
' multiply a quadruple-precision number (a) by a double-precision number (b).
Dim As quad c, z
' local variables
Dim As Double zz
z = exactmul2(a.hi, b)
asm
' zz = a.lo * b + z.lo
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax] 'a.lo
mov eax, dword Ptr [b]
movsd xmm1, qword Ptr [eax] 'b
mulsd xmm0, xmm1 'a.lo * b
movsd xmm1, qword Ptr [z+8]'z.lo
addsd xmm0, xmm1 'a.lo * b + z.lo
movsd qword Ptr [zz], xmm0 '-> zz
' c.hi = z.hi + zz
movsd xmm0, qword Ptr [z] 'z.hi
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1 'z.hi + zz
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0 '-> c.hi
' c.lo = (z.hi - c.hi) + zz
lea eax, dword Ptr [c]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1 'z.hi - c.hi
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1 '(z.hi - c.hi) + zz
lea eax, dword Ptr [c]
movsd qword Ptr [8+eax], xmm0 '-> c.lo
End asm
Return c
End Function
Function mult_quad_Real(Byref a As quad, Byref b As Single) As quad 'Result(c)
' Multiply a quadruple-precision number (a) by a Real number (b).
' Local variables
Dim As quad z, c
Dim As Double zz
z = exactmul2(a.hi, Cdbl(b))
asm
' zz = a.lo * b + z.lo
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax] 'a.lo
mov eax, dword Ptr [b]
movss xmm1, dword Ptr [eax]
cvtss2sd xmm1, xmm1
mulsd xmm0, xmm1
movsd xmm1, qword Ptr [z+8] 'z.lo
addsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' c.hi = z.hi + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0
' c.lo = (z.hi - c.hi) + zz
lea eax, dword Ptr [c]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [8+eax], xmm0
End asm
Return c
End Function 'mult_quad_Real
Function mult_dp_quad(Byref b As Double, Byref a As quad) As quad 'Result(c)
' Multiply a quadruple-precision number (a) by a double-precision number (b).
' Local variables
Dim As quad z, c
Dim As Double zz
z = exactmul2(a.hi, b)
asm
' zz = a.lo * b + z.lo
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax]
mov eax, dword Ptr [b]
movsd xmm1, qword Ptr [eax]
mulsd xmm0, xmm1
movsd xmm1, qword Ptr [z+8]
addsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' c.hi = z.hi + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0
' c.lo = (z.hi - c.hi) + zz
lea eax, dword Ptr [c]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [8+eax], xmm0
End asm
Return c
End Function 'mult_dp_quad
Function mult_Real_quad(Byref a As Single, Byref b As quad) As quad 'Result(c)
' Multiply a quadruple-precision number (a) by a double-precision number (b).
' Local variables
Dim As quad z, c
Dim As Double zz
z = exactmul2(b.hi, Cdbl(a))
asm
' zz = b.lo * a + z.lo
mov eax, dword Ptr [b]
movsd xmm0, qword Ptr [8+eax]
mov eax, dword Ptr [a]
movss xmm1, dword Ptr [eax]
cvtss2sd xmm1, xmm1
mulsd xmm0, xmm1
movsd xmm1, qword Ptr [z+8]
addsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' c.hi = z.hi + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0
' c.lo = (z.hi - c.hi) + zz
lea eax, dword Ptr [c]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [8+eax], xmm0
End asm
Return c
End Function 'mult_Real_quad
Function longdiv(Byref a As quad, Byref c As quad) As quad 'Result(ac)
' Procedure longdiv, translated from Pascal, from:
' Linnainmaa, Seppo (1981). Software for doubled-precision floating-point
' computations. ACM Trans. on Math. Software (TOMS), 7, 272-283.
' Local variables
Dim As Double z, zz
Dim As quad q, ac
z = a.hi / c.hi
q = exactmul2(c.hi, z)
asm
' zz = ((((a.hi - q.hi) - q.lo) + a.lo) - z*c.lo) / (c.hi + c.lo)
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax]
addsd xmm0, xmm1
movsd xmm1, qword Ptr [z]
mov eax, dword Ptr [c]
movsd xmm2, qword Ptr [8+eax]
mulsd xmm1, xmm2
subsd xmm0, xmm1
mov eax, dword Ptr [c]
mov edx, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
movsd xmm2, qword Ptr [8+edx]
addsd xmm1, xmm2
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'longdiv
Function div_quad_dp(Byref a As quad, Byref b As Double) As quad 'Result(c)
' Divide a quadruple-precision number (a) by a double-precision number (b)
' Local variables
Dim As Double z, zz
Dim As quad q, c
z = a.hi / b
q = exactmul2(b, z)
asm
' zz = (((a.hi - q.hi) - q.lo) + a.lo) / b
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax]
addsd xmm0, xmm1
mov eax, dword Ptr [b]
movsd xmm1, qword Ptr [eax]
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' c.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0
' c.lo = (z - c.hi) + zz
lea eax, dword Ptr [c]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [8+eax], xmm0
End asm
Return c
End Function 'div_quad_dp
Function div_quad_Real(Byref a As quad, Byref b As Single) As quad'Result(c)
' Divide a quadruple-precision number (a) by a Real number (b)
' Local variables
Dim As Double z, zz
Dim As quad q, c
z = a.hi / b
q = exactmul2(Cdbl(b), z)
asm
' zz = (((a.hi - q.hi) - q.lo) + a.lo) / b
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax]
addsd xmm0, xmm1
mov eax, dword Ptr [b]
movss xmm1, dword Ptr [eax]
cvtss2sd xmm1, xmm1
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' c.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0
End asm
Return c
End Function 'div_quad_Real
Function div_quad_int(Byref a As quad, Byref b As Integer) As quad 'Result(c)
' Divide a quadruple-precision number (a) by an Integer (b)
' Local variables
Dim As Double z, zz
Dim As quad q, c
z = a.hi / b
q = exactmul2(Cdbl(b), z)
asm
' zz = (((a.hi - q.hi) - q.lo) + a.lo) / b
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax]
addsd xmm0, xmm1
mov eax, dword Ptr [b]
mov eax, dword Ptr [eax]
cvtsi2sd xmm1, eax
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' c.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [eax], xmm0
' c.lo = (z - c.hi) + zz
lea eax, dword Ptr [c]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [c]
movsd qword Ptr [8+eax], xmm0
End asm
Return c
End Function 'div_quad_int
Function div_int_quad(Byref a As Integer, Byref c As quad) As quad 'Result(ac)
' Procedure longdiv, translated from Pascal, from:
' Linnainmaa, Seppo (1981). Software for doubled-precision floating-point
' computations. ACM Trans. on Math. Software (TOMS), 7, 272-283.
' Local variables
Dim As Double z, zz
Dim As quad q, ac
z = Cdbl(a) / c.hi
q = exactmul2(c.hi, z)
asm
' zz = (((a - q.hi) - q.lo) - z*c.lo) / (c.hi + c.lo)
mov eax, dword Ptr [a]
mov eax, dword Ptr [eax]
cvtsi2sd xmm0, eax
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [z]
mov eax, dword Ptr [c]
movsd xmm2, qword Ptr [8+eax]
mulsd xmm1, xmm2
subsd xmm0, xmm1
mov eax, dword Ptr [c]
mov edx, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
movsd xmm2, qword Ptr [8+edx]
addsd xmm1, xmm2
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'div_int_quad
Function div_Real_quad(Byref a As Single, Byref c As quad) As quad 'Result(ac)
' Procedure longdiv, translated from Pascal, from:
' Linnainmaa, Seppo (1981). Software for doubled-precision floating-point
' computations. ACM Trans. on Math. Software (TOMS), 7, 272-283.
' Local variables
Dim As Double z, zz
Dim As quad q, ac
z = Cdbl(a) / c.hi
q = exactmul2(c.hi, z)
asm
' zz = (((a - q.hi) - q.lo) - z*c.lo) / (c.hi + c.lo)
mov eax, dword Ptr [a]
movss xmm0, dword Ptr [eax]
cvtss2sd xmm0, xmm0
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [z]
mov eax, dword Ptr [c]
movsd xmm2, qword Ptr [8+eax]
mulsd xmm1, xmm2
subsd xmm0, xmm1
mov eax, dword Ptr [c]
mov edx, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
movsd xmm2, qword Ptr [8+edx]
addsd xmm1, xmm2
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'div_Real_quad
Function div_dp_quad(Byref a As Double, Byref c As quad) As quad 'Result(ac)
' Procedure longdiv, translated from Pascal, from:
' Linnainmaa, Seppo (1981). Software for doubled-precision floating-point
' computations. ACM Trans. on Math. Software (TOMS), 7, 272-283.
' Local variables
Dim As Double z, zz
Dim As quad q, ac
z = a / c.hi
q = exactmul2(c.hi, z)
asm
' zz = (((a - q.hi) - q.lo) - z*c.lo) / (c.hi + c.lo)
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [q]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [q+8]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [z]
mov eax, dword Ptr [c]
movsd xmm2, qword Ptr [8+eax]
mulsd xmm1, xmm2
subsd xmm0, xmm1
mov eax, dword Ptr [c]
mov edx, dword Ptr [c]
movsd xmm1, qword Ptr [eax]
movsd xmm2, qword Ptr [8+edx]
addsd xmm1, xmm2
divsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'div_dp_quad
Function longadd(Byref a As quad, Byref c As quad) As quad
' procedure longadd, translated from pascal, from:
' linnainmaa, seppo (1981). software for doubled-precision floating-point
' computations. acm trans. on math. software (toms), 7, 272-283.
Dim As quad ac
' local variables
Dim As Double z, q, zz
asm
' z = a.hi + c.hi
mov eax, dword Ptr [a]
mov edx, dword Ptr [c]
movsd xmm0, qword Ptr [eax] 'a
movsd xmm1, qword Ptr [edx] 'c
addsd xmm0, xmm1 'a.hi + c.hi
movsd qword Ptr [z], xmm0 '-> z
' q = a.hi - z
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [eax]
movsd xmm1, qword Ptr [z]
subsd xmm0, xmm1 'a.hi - z
movsd qword Ptr [q], xmm0 '-> q
' zz = (((q + c.hi) + (a.hi - (q + z))) + a.lo) + c.lo
mov eax, dword Ptr [c]
movsd xmm0, qword Ptr [q]
movsd xmm1, qword Ptr [eax]
addsd xmm0, xmm1 'q + c.hi
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [q]
movsd xmm2, qword Ptr [z]
addsd xmm1, xmm2 'q + z
movsd xmm2, qword Ptr [eax] 'a.hi
subsd xmm2, xmm1 'a.hi - (q + z)
addsd xmm0, xmm2 '(q + c.hi) + (a.hi - (q + z))
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax] 'a.lo
addsd xmm0, xmm1 '(((q + c.hi) + (a.hi - (q + z))) + a.lo)
mov eax, dword Ptr [c]
movsd xmm1, qword Ptr [8+eax] 'c.lo
addsd xmm0, xmm1 '(((q + c.hi) + (a.hi - (q + z))) + a.lo) + c.lo
movsd qword Ptr [zz], xmm0 '-> zz
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1 'z + zz
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0 '-> ac.hi
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax] 'ac.hi
subsd xmm0, xmm1 'z - ac.hi
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1 '(z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0 '-> ac.lo
End asm
Return ac
End Function
Function quad_add_int(Byref a As quad, Byref c As Integer) As quad 'Result(ac)
' Local variables
Dim As Double z, q, zz
Dim As quad ac
z = a.hi + c
q = a.hi - z
asm
' zz = (((q + c) + (a.hi - (q + z))) + a.lo)
mov eax, dword Ptr [c]
mov eax, dword Ptr [eax]
cvtsi2sd xmm0, eax
movsd xmm1, qword Ptr [q]
addsd xmm1, xmm0
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [q]
movsd xmm2, qword Ptr [z]
addsd xmm0, xmm2
movsd xmm2, qword Ptr [eax]
subsd xmm2, xmm0
addsd xmm1, xmm2
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax]
addsd xmm1, xmm0
movsd qword Ptr [zz], xmm1
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'quad_add_int
Function quad_add_Real(Byref a As quad, Byref c As Single) As quad 'Result(ac)
' Local variables
Dim As Double z, q, zz
Dim As quad ac
z = a.hi + c
q = a.hi - z
asm
' zz = (((q + c) + (a.hi - (q + z))) + a.lo)
mov eax, dword Ptr [c]
movss xmm0, dword Ptr [eax]
cvtss2sd xmm0, xmm0
movsd xmm1, qword Ptr [q]
addsd xmm1, xmm0
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [q]
movsd xmm2, qword Ptr [z]
addsd xmm0, xmm2
movsd xmm2, qword Ptr [eax]
subsd xmm2, xmm0
addsd xmm1, xmm2
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax]
addsd xmm1, xmm0
movsd qword Ptr [zz], xmm1
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'quad_add_Real
Function quad_add_dp(Byref a As quad, Byref c As Double) As quad 'Result(ac)
' Local variables
Dim As Double z, q, zz
Dim As quad ac
z = a.hi + c
q = a.hi - z
asm
' zz = (((q + c) + (a.hi - (q + z))) + a.lo)
mov eax, dword Ptr [c]
movsd xmm0, qword Ptr [q]
movsd xmm1, qword Ptr [eax]
addsd xmm0, xmm1
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [q]
movsd xmm2, qword Ptr [z]
addsd xmm1, xmm2
movsd xmm2, qword Ptr [eax]
subsd xmm2, xmm1
addsd xmm0, xmm2
mov eax, dword Ptr [a]
movsd xmm1, qword Ptr [8+eax]
addsd xmm0, xmm1
movsd qword Ptr [zz], xmm0
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'quad_add_dp
Function int_add_quad(Byref c As Integer, Byref a As quad) As quad 'Result(ac)
' Local variables
Dim As Double z, q, zz
Dim As quad ac
z = a.hi + c
q = a.hi - z
asm
' zz = (((q + c) + (a.hi - (q + z))) + a.lo)
mov eax, dword Ptr [c]
mov eax, dword Ptr [eax]
cvtsi2sd xmm0, eax
movsd xmm1, qword Ptr [q]
addsd xmm1, xmm0
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [q]
movsd xmm2, qword Ptr [z]
addsd xmm0, xmm2
movsd xmm2, qword Ptr [eax]
subsd xmm2, xmm0
addsd xmm1, xmm2
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax]
addsd xmm1, xmm0
movsd qword Ptr [zz], xmm1
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'int_add_quad
Function Real_add_quad(Byref c As Single, Byref a As quad) As quad 'Result(ac)
' Local variables
Dim As Double z, q, zz
Dim As quad ac
z = a.hi + c
q = a.hi - z
asm
' zz = (((q + c) + (a.hi - (q + z))) + a.lo)
mov eax, dword Ptr [c]
movss xmm0, dword Ptr [eax]
cvtss2sd xmm0, xmm0
movsd xmm1, qword Ptr [q]
addsd xmm1, xmm0
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [q]
movsd xmm2, qword Ptr [z]
addsd xmm0, xmm2
movsd xmm2, qword Ptr [eax]
subsd xmm2, xmm0
addsd xmm1, xmm2
mov eax, dword Ptr [a]
movsd xmm0, qword Ptr [8+eax]
addsd xmm1, xmm0
movsd qword Ptr [zz], xmm1
' ac.hi = z + zz
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [eax], xmm0
' ac.lo = (z - ac.hi) + zz
lea eax, dword Ptr [ac]
movsd xmm0, qword Ptr [z]
movsd xmm1, qword Ptr [eax]
subsd xmm0, xmm1
movsd xmm1, qword Ptr [zz]
addsd xmm0, xmm1
lea eax, dword Ptr [ac]
movsd qword Ptr [8+eax], xmm0
End asm
Return ac
End Function 'Real_add_quad