Very very nice usage of Oxygen.
Charles will be happy
i tested the ext floating point type but ist's too slow for my needs.
so here is what i use as include file.
currently i use 3D vectors as array
dim a(3) as single
dim b(3) as single
dim c(3) as single
dim d as single
a(1) = 1,2,3
b(1) = 2,3,4
VecCrossAB(c,a,b) ' c = a x b
VecAdd(a,b) ' a += b
VecSub(a,b) ' a -= b
VecAddAB(c,a,b) ' c = a + b
VecSubAB(c,a,b) ' c = a - b
VecMulS(a,123.45) ' a*=scalar
VecMulABS(a,b,123.45) ' a=b*scalar
d=Length(a) ' sqr(ax*ax + ay*ay + az*az)
d=VecDistanceAB(a,b) ' d = srq((az-bz)*(az-bz) + (ay-by)*(ay-by) + (ax-bx)*(ax-bx))
d=dot(a) ' d=ax*ax + ay*ay + az*az
d=dotAB(a,B) ' d=ax*bx + ay*by + az*bz
...
happy coding
Joshy
[code=thinbasic]' litle bit vector math
uses "OXYGEN"
Begin Const
%BUFFER_SET = 1
%BUFFER_COPY
%BUFFER_ADD
%BUFFER_SUB
%BUFFER_ADDAB
%BUFFER_SUBAB
%BUFFER_MULS
%BUFFER_MULABS
%BUFFER_DOT
%BUFFER_DOTAB
%BUFFER_DISTANCEAB2 ' squared
%BUFFER_DISTANCEAB
%BUFFER_LENGTH
%BUFFER_NORMALIZE2 ' v*=1/sqr(squared)
%BUFFER_CROSSAB
%BUFFER_SQRT
End Const
Dim src As String
'######################
' VecSet(R(),X,Y,Z)
'######################
src = "
mov edi,[esp+ 4] ; r()
mov eax,[esp+ 8]
mov [edi],eax ; r(1)=x
mov eax,[esp+12]
mov [edi+4],eax ; r(2)=y
mov eax,[esp+16]
mov [edi+8],eax ; r(3)=z
ret 16
"
O2_BUF %BUFFER_SET : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'######################
' VecCopy(R(),A())
' r()=a()
'######################
src = "
mov edi,[esp+ 4] ; r()
mov esi,[esp+ 8] ; a()
mov eax,[esi]
mov [edi],eax ; r(1)=a(1)
mov eax,[esi+4]
mov [edi+4],eax ; r(2)=a(2)
mov eax,[esi+8]
mov [edi+8],eax ; r(3)=a(3)
ret 8
"
O2_BUF %BUFFER_COPY : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'######################
' VecAdd(A(),B())
' a()+=b()
'######################
src = "
mov edi,[esp+ 4] ; a()
mov esi,[esp+ 8] ; b()
fld dword [edi ]
fadd dword [esi ]
fstp dword [edi ] ; ax+=bx
fld dword [edi+4]
fadd dword [esi+4]
fstp dword [edi+4] ; ay+=by
fld dword [edi+8]
fadd dword [esi+8]
fstp dword [edi+8] ; az+=bz
ret 8
"
O2_BUF %BUFFER_ADD : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'######################
' VecSub(A(),B())
' a()-=b()
'######################
src = "
mov edi,[esp+ 4] ; a()
mov esi,[esp+ 8] ; b()
fld dword [edi ]
fsub dword [esi ]
fstp dword [edi ] ; ax-=bx
fld dword [edi+4]
fsub dword [esi+4]
fstp dword [edi+4] ; ay-=by
fld dword [edi+8]
fsub dword [esi+8]
fstp dword [edi+8] ; az-=bz
ret 8
"
O2_BUF %BUFFER_SUB: O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'#######################
' VecAddAB(R(),A(),B())
' r()=a()+b()
'#######################
src = "
mov eax,[esp+ 4] ; r()
mov esi,[esp+ 8] ; a()
mov edi,[esp+12] ; b()
fld dword [esi ]
fadd dword [edi ]
fstp dword [eax ] ; rx = (ax+bx)
fld dword [esi+4]
fadd dword [edi+4]
fstp dword [eax+4] ; ry = (ay+by)
fld dword [esi+8]
fadd dword [edi+8]
fstp dword [eax+8] ; rz = (az+bz)
ret 12
"
O2_BUF %BUFFER_ADDAB: O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'#######################
' VecSubAB(R(),A(),B())
' r()=a()-b()
'#######################
src = "
mov eax,[esp+ 4] ; r()
mov esi,[esp+ 8] ; a()
mov edi,[esp+12] ; b()
fld dword [esi ]
fsub dword [edi ]
fstp dword [eax ] ; rx = (ax-bx)
fld dword [esi+4]
fsub dword [edi+4]
fstp dword [eax+4] ; ry = (ay-by)
fld dword [esi+8]
fsub dword [edi+8]
fstp dword [eax+8] ; rz = (az-bz)
ret 12
"
O2_BUF %BUFFER_SUBAB: O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'################
' VecMulS(A(),S)
' a()*=s
'################
src = ";
mov esi , [esp+4]
fld dword [esp+8] ; s
fmul dword [esi ] ;s*x,s
fstp dword [esi ] ; s
fmul dword [esi+4] ;s*y,s
fstp dword [esi+4] ;s
fmulp dword [esi+8] ;s*z
fstp dword [esi+8]
ret 8
"
O2_BUF %BUFFER_MULS : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'######################
' VecMulABS(R(),A(),S)
' r()=b()*s
'######################
src = "
mov edi , [esp+ 4] ; r()
mov esi , [esp+ 8] ; b()
fld dword [esp+12] ; s
fld dword [esi ] ; bx,s
fmul ; ax*s,s
fstp dword [edi ] ; s
fld dword [esi+4] ; by,s
fmul ; ay*s,s
fstp dword [edi+4] ; s
fld dword [esi+8] ; bz,s
fmulp ; az*s
fstp dword [edi+8]
ret 12
"
O2_BUF %BUFFER_MULABS : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'#######################
' s = VecDot(a())
' s = ax*ax+ay*ay+az*az
'#######################
src = ";
mov esi , [esp+4]
fld dword [esi ] ; (x)
fld st(0) ; (x),(x)
fmulp ; (x*x)
fld dword [esi+4] ; (y),(x*x)
fld st(0) ; (y),(y),(x*x)
fmulp ; (y*y),(x*x)
fld dword [esi+8] ; (z),(y*y),(x*x)
fld st(0) ; (z),(z),(y*y),(x*x)
fmulp ; (z*z),(y*y),(x*x)
faddp ; (z*z + y*y),(x*x)
faddp ; (z*z + y*y + x*x)
ret 4
"
O2_BUF %BUFFER_DOT : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'#######################
' s = VecDotAB(a(),b())
' s = ax*bx+ay*by+az*bz
'#######################
src = "
mov esi, [esp+4]
mov edi, [esp+8]
fld dword [edi ] ; (bx)
fmul dword [esi ] ; (ax*bx)
fld dword [edi+4] ; (by),(ax*bx)
fmul dword [esi+4] ; (ay*by),(ax*bx)
fld dword [edi+8] ; (bz),(ay*by),(ax*bx)
fmul dword [esi+8] ; (az*bz),(ay*by),(ax*bx)
faddp ; (az*bz + ay*by),(ax*bx)
faddp ; (az*bz + ay*by + ax*bx)
ret 8
"
O2_BUF %BUFFER_DOTAB : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'###########################
' s = VecDistanceAB2(a(),b())
' s = dot(a()-b())
'###########################
src = "
mov esi,[esp+4]
mov edi,[esp+8]
fld dword [esi ] ; (ax)
fsub dword [edi ] ; (ax-bx)
fld st(0) ; (ax-bx),(ax-bx)
fmulp ; (ax-bx)*(ax-bx)
fld dword [esi+4] ; (ay),(ax-bx)*(ax-bx)
fsub dword [edi+4] ; (ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (ay-by),(ay-by),(ax-bx)*(ax-bx)
fmulp ; (ay-by)*(ay-by),(ax-bx)*(ax-bx)
fld dword [esi+8] ; (az),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fsub dword [edi+8] ; (az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (az-bz),(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fmulp ; (az-bz)*(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
faddp ; (az-bz)*(az-bz)+(ay-by)*(ay-by),(ax-bx)*(ax-bx)
faddp ; (az-bz)*(az-bz)+(ay-by)*(ay-by)+(ax-bx)*(ax-bx)
ret 8
"
O2_BUF %BUFFER_DISTANCEAB2 : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'############################
' s = VecDistanceAB(a(),b())
' s = Sqr(Distance2(a()-b())
'############################
src = "
mov esi,[esp+4]
mov edi,[esp+8]
fld dword [esi ] ; (ax)
fsub dword [edi ] ; (ax-bx)
fld st(0) ; (ax-bx),(ax-bx)
fmulp ; (ax-bx)*(ax-bx)
fld dword [esi+4] ; (ay),(ax-bx)*(ax-bx)
fsub dword [edi+4] ; (ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (ay-by),(ay-by),(ax-bx)*(ax-bx)
fmulp ; (ay-by)*(ay-by),(ax-bx)*(ax-bx)
fld dword [esi+8] ; (az),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fsub dword [edi+8] ; (az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (az-bz),(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fmulp ; (az-bz)*(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
faddp ; (az-bz)*(az-bz)+(ay-by)*(ay-by),(ax-bx)*(ax-bx)
faddp ; (az-bz)*(az-bz)+(ay-by)*(ay-by)+(ax-bx)*(ax-bx)
fsqrt ; srq(distance2(a(),b())
ret 8
"
O2_BUF %BUFFER_DISTANCEAB : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'############################
' s = VecLength(a())
' s = sqr(ax*ax+ay*ay+az*az)
'############################
src = ";
mov esi , [esp+4]
fld dword [esi ] ; (x)
fld st(0) ; (x),(x)
fmulp ; (x*x)
fld dword [esi+4] ; (y),(x*x)
fld st(0) ; (y),(y),(x*x)
fmulp ; (y*y),(x*x)
fld dword [esi+8] ; (z),(y*y),(x*x)
fld st(0) ; (z),(z),(y*y),(x*x)
fmulp ; (z*z),(y*y),(x*x)
faddp ; (z*z + y*y),(x*x)
faddp ; (z*z + y*y + x*x)
fsqrt
ret 4
"
O2_BUF %BUFFER_LENGTH : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'############################
' s = VecNormlize2(a(),squared)
' a()*1/sqr(squared)
'############################
src = "
mov esi,[esp+4] ; a()
fld dword [esp+8] ; x*x+y*y+z*z
fsqrt ; sqr(x*x+y*y+z*z)
fld1 ; 1.0,sqr(x*x+y*y+z*z)
fdiv ; invsqr
fld dword [esi] ; x,invsqr
fmul ; x*invsqr,invsqr
fstp dword [esi] ; invsqr
fld dword [esi+4] ; y,invsqr
fmul ; y*invsqr,invsqr
fstp dword [esi+4] ; invsqr
fld dword [esi+8] ; z,invsqr
fmulp ; z*invsqr
fstp dword [esi+8]
ret 8
"
O2_BUF %BUFFER_NORMALIZE2 : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'############################
' s = SQRT(a)
'############################
src = "
fld dword [esp+4]
fsqrt
ret 4
"
O2_BUF %BUFFER_SQRT : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
'#####################################
' VecCrossAB(r(),a(),b())
' r(1)=(a[Y] * b[Z]) - (a[Z] * b[Y])
' r(2)=(a[Z] * b[X]) - (a[X] * b[Z])
' r(3)=(a[X] * b[Y]) - (a[Y] * b[X])
'#####################################
src = "
mov edi , [esp+ 4] ; r()
mov eax , [esp+ 8] ; a()
mov esi , [esp+12] ; b()
fld dword [esi+4] ; by
fld dword [eax+8] ; az ,by
fmulp ; az*by
fld dword [esi+8] ; bz ,az*by
fld dword [eax+4] ; ay ,bz ,az*by
fmulp ; ay*bz,az*by
fsub ; ay*bz-az*by
fstp dword [edi ] ; rx=ay*bz-az*by
fld dword [esi+8] ; bz
fld dword [eax ] ; ax,bz
fmulp ; ax*bz
fld dword [esi ] ; bx,ax*bz
fld dword [eax+8] ; az,bx,ax*bz
fmulp ; az*bx,ax*bz
fsub ; az*bx-ax*bz
fstp dword [edi+4] ; ry=az*bx-ax*bz
fld dword [esi ] ; bx
fld dword [eax+4] ; ay,bx
fmulp ; ay*bx
fld dword [esi+4] ; by,ay*bx
fld dword [eax ] ; ax,by,ay*bx
fmulp ; ax*by,ay*bx
fsub ; ax*by-ay*bx
fstp dword [edi+8] ; rz=ax*by-ay*bx
ffree st(2)
ffree st(1)
ffree st(0)
ret 12
"
O2_BUF %BUFFER_CROSSAB : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If
Declare Sub VecSet (ByRef a() As Single, ByVal x As Single,ByVal y As Single,ByVal z As Single) At O2_BUF %BUFFER_SET
Declare Sub VecCopy (ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_COPY
Declare Sub VecAdd (ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_ADD
Declare Sub VecSub (ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_SUB
Declare Sub VecAddAB (ByRef r() As Single, ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_ADDAB
Declare Sub VecSubAB (ByRef r() As Single, ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_SUBAB
Declare Function VecMulS (ByRef a() As Single, ByVal s As Single) As Single At O2_BUF %BUFFER_MULS
Declare Function VecMulAS (ByRef r() As Single, ByRef a() As Single, ByVal s As Single) As Single At O2_BUF %BUFFER_MULABS
Declare Function VecDot (ByRef a() As Single) As Single At O2_BUF %BUFFER_DOT
Declare Function VecDotAB (ByRef a() As Single,ByRef b() As Single) As Single At O2_BUF %BUFFER_DOTAB
Declare Function VecDistanceAB2(ByRef a() As Single,ByRef b() As Single) As Single At O2_BUF %BUFFER_DISTANCEAB2
Declare Function VecDistanceAB (ByRef a() As Single,ByRef b() As Single) As Single At O2_BUF %BUFFER_DISTANCEAB
Declare Function VecLength (ByRef a() As Single) As Single At O2_BUF %BUFFER_LENGTH
Declare Sub VecNormalize2 (ByRef a() As Single,ByVal Lenght2 As Single) As Single At O2_BUF %BUFFER_NORMALIZE2
Declare Sub VecCrossAB (ByRef r() As Single, ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_CROSSAB
Declare Function Sqrt (ByVal v As Single) As Single At O2_BUF %BUFFER_SQRT
Sub VecNormalize(ByRef a() As Single)
Local s As Single
s=VecDot(a)
If s=0 Then Return
VecNormalize2(a,s)
End Sub
Function VecCos(ByRef a() As Single, ByRef b() As Single) As Single
Dim l1,l2 As Single
l1 = VecDot(a) ' x*0=0
If l1=0 Then Return 0
l2 = VecDot(b) ' y*0=0
If l2=0 Then Return 0
l2 = SQRT(l1)*SQRT(l2)
l1 = VecDot(a,b)
Return l1/l2 ' acos(l1/l2)
End Function
[/code]
(Sorry about my bad English.)
Very very nice usage of Oxygen.
Charles will be happy
www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000
Thanks Joshy!
Looking at your code I have just realised that it would be useful to be able to generate DLLs with exportable assembler functions (as well as BASIC). So I am going to add this facility to Oxygen now.
proposed syntax for an exported label:
MyAsmFunction: alias "MyAsmFunction" export
Charles
Looks like the function call from interpreter to inline assembler functions are very slow.
I wrote a short test raytracer program where you can switch between interpreter
vector math and the inline assembler math.
But both results was near 46 seconds for one ray per pixel and a scene with 3 spheres.
Normaly the inline assembler math should be 10-100 times faster as the interpreter math.
Joshy
(i hat closed source codes )
(Sorry about my bad English.)
Hi Joshy,
Ray tracing sounds hard work for an interpreter!
If you would like to post your test ray tracer here, I will try to accelerate it with Oxygen Basic and see whether we can get it to run at an acceptable speed.
Charles
One observation on your Assembler functions:
The esi and edi registers normally need to be preserved. ThinBasic does this already but in a general DLL this would be a necessity for STDCALL or CDECL calls. For these vector functions I would use the ecx and edx registers instead.
Charles
Bookmarks