Re: Word Count
Posted: Wed Jul 30, 2014 10:05 pm
Danilo, I am studying your code, thank you 
Glad to hear it is working for youspacebuddy wrote:Wilbert, I tested this on my machine and it is smoking fast
Code: Select all
Procedure.i CountWords(*Text.Character); Requires MMX
; init some mmx registers
!pcmpeqd mm2, mm2
!pxor mm3, mm3
!psubd mm3, mm2
!pslld mm3, 5
!pxor mm2, mm2
!pxor mm1, mm1
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Text]
CompilerElse
!mov edx, [p.p_Text]
CompilerEndIf
!jmp countwords_entry
; main loop
!countwords_loop:
!pcmpgtd mm0, mm3
!pandn mm1, mm0
!psubd mm2, mm1
!movq mm1, mm0
; entry point for first character
!countwords_entry:
CompilerIf #PB_Compiler_Unicode
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!movzx eax, word [rdx]
!add rdx, 2
CompilerElse
!movzx eax, word [edx]
!add edx, 2
CompilerEndIf
CompilerElse
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!movzx eax, byte [rdx]
!add rdx, 1
CompilerElse
!movzx eax, byte [edx]
!add edx, 1
CompilerEndIf
CompilerEndIf
!movd mm0, eax
; loop if not end of string
!and ax, ax
!jnz countwords_loop
; set result and empty mmx state
!movd eax, mm2
!emms
ProcedureReturn
EndProcedureCode: Select all
Structure WordAndLFCount
WordCount.l
LFCount.l
Len.l
EndStructure
Procedure CountWordsAndLF(*Text, *TextInfo.WordAndLFCount); Requires MMX
; init some mmx registers
!pcmpeqd mm2, mm2
!pxor mm3, mm3
!psubd mm3, mm2
!pslld mm3, 5
!pxor mm2, mm2
!pxor mm1, mm1
!xor ecx, ecx
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_Text]
CompilerElse
!mov edx, [p.p_Text]
CompilerEndIf
!jmp countwords_entry
; main loop
!countwords_loop:
!pcmpgtd mm0, mm3
!pandn mm1, mm0
!psubd mm2, mm1
!movq mm1, mm0
; entry point for first character
!countwords_entry:
CompilerIf #PB_Compiler_Unicode
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!movzx eax, word [rdx]
!add rdx, 2
CompilerElse
!movzx eax, word [edx]
!add edx, 2
CompilerEndIf
CompilerElse
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!movzx eax, byte [rdx]
!add rdx, 1
CompilerElse
!movzx eax, byte [edx]
!add edx, 1
CompilerEndIf
CompilerEndIf
!movd mm0, eax
; loop if not end of string
!test ax, 0xfff5
!jnz countwords_loop
!cmp ax, 9
!sbb ecx, -1
!and ax, ax
!jnz countwords_loop
; set result and empty mmx state
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!sub rdx, [p.p_Text]
CompilerIf #PB_Compiler_Unicode
!shr rdx, 1
CompilerEndIf
!dec edx
!mov rax, [p.p_TextInfo]
!movd [rax], mm2
!mov [rax + 4], ecx
!mov [rax + 8], edx
CompilerElse
!sub edx, [p.p_Text]
CompilerIf #PB_Compiler_Unicode
!shr edx, 1
CompilerEndIf
!dec edx
!mov eax, [p.p_TextInfo]
!movd [eax], mm2
!mov [eax + 4], ecx
!mov [eax + 8], edx
CompilerEndIf
!emms
ProcedureReturn
EndProcedureCode: Select all
S.s = "This is a test string" + #LF$
For i = 1 To 15
S + S
Next
CountWordsAndLF(@S, @TextInfo.WordAndLFCount)
Debug TextInfo\WordCount
Debug TextInfo\LFCount
Debug TextInfo\LenCode: Select all
S.s = "This is a test string" + #LF$
For i = 1 To 23
S + S
Next
dt = ElapsedMilliseconds()
CountWordsAndLF(@S, @TextInfo.WordAndLFCount)
With TextInfo
MessageRequester("Time: " + Str(ElapsedMilliseconds() - dt),"WordCount: " + Str(\WordCount) + Chr(10) + "LFCount: " + Str(\LFCount) + Chr(10) + "Len: " + Str(\Len))
EndWith