Comparisons in mathematical simulations

Just starting out? Need help? Post your questions and find answers here.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Comparisons in mathematical simulations

Post by wilbert »

I think for a unique key there's no need to append the z characters.
Without appending them (just 171 and 4221) the key should still be unique.
Windows (x64)
Raspberry Pi OS (Arm64)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Comparisons in mathematical simulations

Post by wilbert »

My ASM attempt (Wilbert_v2 version).

I changed .s into .s{10} for a1 and a2.
This way always 10 characters are available.
If you use .s, you have to make sure yourself that the string is large enough to hold the result before you pass the string address.

Code: Select all

DisableDebugger
Global Dim vet1.i(100): Global Dim vet2.i(100)
Define.i i,j
Define.s{10} a1,a2
RandomSeed(0)
For i=0 To 100: vet1(i)=Random(10,1): vet2(i)=Random(10,1): Next    

Procedure.s Year2011(*String1,qt.i,flag.i)   ; String1 from 00 to 99 with spaces | qt = 2 to 50 = len(String1+1)/3  | flag= 1 in vet1() or 0 in vet2()
  Protected Dim dr.i(21)
  Protected.i i,j
  Protected.s aux
  For i=1 To qt
    aux=PeekS(*String1+(i-1)*6,2): If flag: dr(vet1(Val(aux)))+1: Else: dr(vet2(Val(aux)))+1: EndIf 
  Next  
  For i=1 To 10: If dr(i)<>0: dr(11+j)=dr(i):j+1: EndIf: Next
  SortArray(dr(),#PB_Sort_Ascending,11,10+j)
  aux="": For i=1 To j: aux+Str(dr(10+i)): Next  
  ProcedureReturn aux
EndProcedure  
Structure StringElement
  StructureUnion
    c.c[2]
    n.l 
  EndStructureUnion
  spacing.c 
EndStructure
Procedure.s Today(*cval.StringElement,qt.i,i2.i) 
  Protected Dim dr.i(21)
  Protected.i i,j,n
  Protected.s aux  
!mov r11, [p.a_dr] 
!mov r8, [a_vet1]   
!mov r9, [a_vet2] 
!mov r13, [p.v_qt]  
!l_loop1:
   n = (*cval\c[0] * 10 + *cval\c[1] - 528)*8
!mov r10,[p.v_n]
    If i2
!mov r14, [r8 + r10]      
!add qword [r11 + r14 * 8], 1      
    Else
!mov r14, [r9 + r10]         
!add qword [r11 + r14 * 8], 1        
    EndIf
    *cval + 6    
!sub r13, 1
!jnz l_loop1

i=0
!mov r13, 10 
!l_loop2:
!add qword [p.v_i], 1  
    If dr(i)<>0: dr(11+j)=dr(i):j+1: EndIf
!sub r13, 1
!jnz l_loop2

SortArray(dr(),#PB_Sort_Ascending,11,10+j)

aux="": For i=1 To j: aux+Str(dr(10+i)): Next  
  ProcedureReturn aux      
EndProcedure
Procedure.s NewIdea(*cval.StringElement,qt.i,i2.i) 
  Protected Dim dr.i(21)
  Protected.i i,j,n
  Protected.s aux  
!mov r11, [p.a_dr] 
!mov r8, [a_vet1]   
!mov r9, [a_vet2] 
!mov r13, [p.v_qt]  
!l_loop1a:
   n = (*cval\c[0] * 10 + *cval\c[1] - 528)*8
!mov r10,[p.v_n]
    If i2
!mov r14, [r8 + r10]      
!add qword [r11 + r14 * 8], 1      
    Else
!mov r14, [r9 + r10]         
!add qword [r11 + r14 * 8], 1        
    EndIf
    *cval + 6    
!sub r13, 1
!jnz l_loop1a

i=0
!mov r13, 10 
!l_loop2a:
!add qword [p.v_i], 1  
     dr(11+dr(i))+1: If dr(i)>j: j=dr(i): EndIf 
!sub r13, 1
!jnz l_loop2a

aux="": For i=1 To j : aux+Str(dr(11+i)): Next  
  ProcedureReturn LSet(aux,10,"z")      
EndProcedure
Procedure.s Wilbert(*cval.StringElement,*where,qt.i,i2.i) 
  Protected Dim dr.i(21)
  Protected.i i,j,n
  Protected.s aux  
!mov r11, [p.a_dr] 
!mov r8, [a_vet1]   
!mov r9, [a_vet2] 
!mov r13, [p.v_qt]  
!l_loop1w:
   n = (*cval\c[0] * 10 + *cval\c[1] - 528)*8
!mov r10,[p.v_n]
    If i2
!mov r14, [r8 + r10]      
!add qword [r11 + r14 * 8], 1      
    Else
!mov r14, [r9 + r10]         
!add qword [r11 + r14 * 8], 1        
    EndIf
    *cval + 6    
!sub r13, 1
!jnz l_loop1w

i=0
!mov r13, 10 
!l_loop2w:
!add qword [p.v_i], 1  
     dr(11+dr(i))+1: If dr(i)>j: j=dr(i): EndIf 
!sub r13, 1
!jnz l_loop2w

  For i=1 To j: PokeS(@where+(i-1)*2,Str(dr(11+i)),1): Next  

  ProcedureReturn    
EndProcedure

Procedure Wilbert_v2(*StringIn, *FixedStringOut, qt.l, flag.l)

  !mov r8, [p.p_StringIn]
  !mov r9, [p.p_FixedStringOut]
  !mov ecx, [p.v_qt]
  !cmp dword [p.v_flag], 0
  !cmovne r10, [a_vet1]
  !cmove  r10, [a_vet2]
  ; allocate some stack memory and clear first 16 bytes
  !sub rsp, 272
  !mov rdx, rsp
  !pxor xmm0, xmm0
  !movdqu [rdx], xmm0
  ; get number from string
  !.l0:
  !mov eax, [r8]
  !and eax, 0xf000f
  !imul eax, 0xa0001
  !shr eax, 16
  !add r8, 6
  ; lookup inside vet array
  !movzx eax, byte [r10 + rax*8]
  ; increase value
  !add byte [rdx + rax], 1
  ; next
  !sub ecx, 1
  !jnz .l0
  
  ; clear 16 bytes for count
  !lea r8, [rdx + 16]
  !movdqu [r8], xmm0
  ; count
  !mov ecx, 10
  !.l1:
  !movzx eax, byte [rdx + rcx]
  !add byte [r8 + rax], 1
  !sub ecx, 1
  !jnz .l1
  ; create output
  !mov ecx, 10
  !.l2:
  !movzx eax, byte [r8 + rcx]
  !cmp eax, 0
  !jne .l4
  !mov eax, 'z'; remove this line if you don't want 'z' padding
  !mov [r9 + rcx*2 - 2], ax
  !sub ecx, 1
  !jnz .l2
  !jmp .l5
  !.l3:
  !movzx eax, byte [r8 + rcx]
  !.l4:
  !add eax, '0'
  !mov [r9 + rcx*2 - 2], ax
  !sub ecx, 1
  !jnz .l3
  !.l5:
  ; restore stack pointer
  !add rsp, 272

EndProcedure  


String1.s="15 12 18 87 95 10 13 21 14 88 80 77 51 53 43 26 81 00 11"

t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again:

a1=Year2011(@String1,18,1)
a2=Year2011(@String1,18,0)

!sub r15, 1                                        
!jnz l_again
Result$+"( In 2011 ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)

t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again1:

a1=Today(@String1,18,1)
a2=Today(@String1,18,0)

!sub r15, 1                                        
!jnz l_again1
Result$+"( Today ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)

t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again2:

a1=NewIdea(@String1,18,1)
a2=NewIdea(@String1,18,0)

!sub r15, 1                                        
!jnz l_again2
Result$+"( New idea ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)

t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again3:

Wilbert(@String1,@a1,18,1)
Wilbert(@String1,@a2,18,0)

!sub r15, 1                                        
!jnz l_again3
Result$+"( Wilbert ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)

t1.i = ElapsedMilliseconds()
!mov r15, 50000
!l_again4:

Wilbert_v2(@String1,@a1,18,1)
Wilbert_v2(@String1,@a2,18,0)

!sub r15, 1                                        
!jnz l_again4
Result$+"( Wilbert_v2 ) result: "+a1+" and "+a2+" in "+StrF((ElapsedMilliseconds()-t1),0)+" ms"+Chr(13)

EnableDebugger
Debug Result$
Windows (x64)
Raspberry Pi OS (Arm64)
fvillanova
User
User
Posts: 70
Joined: Wed May 02, 2012 2:17 am
Location: Brazil

Re: Comparisons in mathematical simulations

Post by fvillanova »

wilbert wrote: Mon May 29, 2023 4:26 pm I think for a unique key there's no need to append the z characters.
Without appending them (just 171 and 4221) the key should still be unique.
Yes, the "z" are not necessary because "0" is in the key when there is no occurrence:
171 is very different from 0171, it will work perfectly.
congratulations Wilbert, it's much faster here!
Now I'm going to put it in all programs that use this procedure.
thanks

p.s.: I put a small detail in your procedure that is now perfect, and the processing time remains practically the same:

Procedure.S Wilbert_v2(*StringIn, *FixedStringOut, qt.l, flag.l)
ProcedureReturn PeekS(*FixedStringOut,10)
Post Reply