Collatz Conjecture Disprover Unit - Googol Edition












0














The Wikipedia article about the Collatz Conjecture has these quotes:




If the conjecture is false, it can only be because there is some starting number which gives rise to a sequence that does not contain 1. Such a sequence might enter a repeating cycle that excludes 1, or increase without bound. No such sequence has been found.



... sometimes a conjecture's only counterexamples are found when using very large numbers.




The bit about using very large numbers motivated me to write the following Collatz calculator that uses Googol-sized numbers.

The program is very extensible. Just change the equates on top.



The faster the calculation, the more numbers can be verified for compliance, silently hoping for non-compliance of course...

I'm most interested in speeding up the CollatzEngine.



I display a running counter on screen just to prove that the program is still alive.



; Copyright (c) 2018, Sep Roland.
; All rights reserved.

PowerOfTen = 100 ;1 Googol == 10^100
MaxDWords = 12 ;1 Googol occupies 11 dwords
MaxSteps = 100000
Width = (1+MaxDWords)*4
STD_OUTPUT_HANDLE = 0FFFFFFF5h

format PE console

Start: mov esi, Title
call PrintString
mov eax, PowerOfTen
call PrintNumber
mov esi, Title_
call PrintString

mov ebx, Slots ;Pointing at SlotA
call BuildGoogol ; -> (EAX ECX..EBP)

Next: mov esi, [Screen] ;Update the counter on screen
call PrintString
call CollatzEngine ; -> ECX (EAX EDX..EDI)
call GoToNextNumber ; -> (EAX ESI)
jmp Next
; --------------------------------------
Fatal3: call Fatal ;From inside CollatzEngine
db "needs too many steps - Possible repetition!", 0
Fatal2: call Fatal ;From inside CollatzEngine
db "grows too big - Possible divergence!", 0
Fatal1: call Fatal ;From outside CollatzEngine
db "needs more space.", 0
Fatal: mov esi, Error
call PrintString
pop esi
call PrintString

mov al, 0
jmp TerminateProgram
; --------------------------------------
; IN (ebx) OUT () MOD (eax,ecx..ebp)
BuildGoogol:
mov ecx, 1
mov [ebx], ecx ;SignificantDWords = 1
mov [ebx+4], ecx ;SlotA = 1
mov ebp, PowerOfTen
jmp .c
.a: lea edi, [ebx+4] ;Current value * 10
xor esi, esi
mov ecx, [ebx] ;SignificantDWords
.b: mov eax, 10
mul dword [edi]
add eax, esi
adc edx, 0
stosd
mov esi, edx
dec ecx
jnz .b
test esi, esi
jz .c
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
mov [edi], esi
inc dword [ebx]
.c: dec ebp
jns .a
ret ;SlotA = 10 ^ #PowerOfTen
; --------------------------------------
; IN (ebx) OUT (ecx) MOD (eax,edx..edi)
CollatzEngine:
mov ecx, [ebx] ;SignificantDWords [1,MaxDWords]
inc ecx
mov esi, ebx
add ebx, Width ;(*) Within Collatz EBX points at SlotB
mov edi, ebx
rep movs dword [edi], [esi] ;Copy SlotA into SlotB

;;xor ecx, ecx ;StepCount
mov esi, [ebx] ;Cache SignificantDWords [1,MaxDWords]
jmp .Start

.Cont: mov eax, [ebx+4] ;Lowest dword of current number
bt eax, 0
adc ecx, 1 ;StepCount + [1,2]
cmp ecx, MaxSteps
ja Fatal3 ;"needs too many steps"

bt eax, 0
jnc @f
call .Odd ; -> ESI CF=0 (EAX EDX EDI)
@@: call .Even ; -> ESI (EAX EDX EDI)

.Start: cmp esi, 1
jne .Cont
cmp [ebx+4], esi
jne .Cont

.Done: mov [ebx], esi ;Un-cache SignificantDWords
sub ebx, Width ;(*) Restore EBX to point at SlotA
ret ;ECX is steps taken to reach 1
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=1) OUT (esi,CF=0) MOD (eax,edx,edi)
.Odd: lea edi, [ebx+Width+4] ;CF=1 This produces the +1
mov edx, esi
@@: mov eax, [edi-Width] ;n --> 2n+1
rcl eax, 1
stosd ;DST is intermediate storage (SlotC)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
mov [edi-Width], edx ;EDX=0
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0

@@: lea edi, [ebx+4] ;CF=0
mov edx, esi
@@: mov eax, [edi] ;2n+1 --> 3n+1
adc eax, [edi+Width]
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0
@@: ret
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=0) OUT (esi) MOD (eax,edx,edi)
.Even: lea edi, [ebx+esi*4] ;CF=0
mov edx, esi
std
@@: mov eax, [edi] ;n --> n/2
rcr eax, 1
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
cld
cmp [ebx+esi*4], edx ;EDX=0
sete dl ; -> EDX=[0,1]
sub esi, edx ;This is Downscale if EDX=1
ret
; --------------------------------------
; IN (ebx) OUT () MOD (eax,esi)
GoToNextNumber:
mov esi, ebx ;Increment number in SlotA
mov eax, [esi] ;SignificantDWords
.a: add esi, 4
add dword [esi], 1
jnc .b
dec eax
jnz .a
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
inc eax ; 0 -> 1
add [ebx], eax
mov [esi+4], eax

.b: lea esi, [Mirror+38] ;Increment counter in mirror
jmp .d
.c: sub al, 10
mov [esi], al
dec esi
cmp esi, [Screen]
jnb .d
mov [Screen], esi
.d: mov al, [esi]
add al, 1
cmp al, "9"
ja .c
mov [esi], al
ret
; --------------------------------------

; IN (al)
TerminateProgram:
movzx eax, al
push eax
call [ExitProcess]

; IN (esi)
PrintString:
push ebx
push esi ;(1)
push STD_OUTPUT_HANDLE
call [GetStdHandle]
mov ebx, eax
pop esi ;(1)
mov edi, esi
or ecx, -1
xor al, al
repne scasb
neg ecx
sub ecx, 2
push 0
push Bytes
push ecx
push esi
push ebx
call [WriteFile]
pop ebx
ret

; IN (dl)
PrintCharacter:
mov [OneChar], dl
push STD_OUTPUT_HANDLE
call [GetStdHandle]
push 0
push Bytes
push 1
push OneChar
push eax
call [WriteFile]
ret

; IN (eax)
PrintNumber:
push ebx
mov ebx, 10 ;CONST 10
push ebx ;Sentinel
.a: xor edx,edx
div ebx
push edx
test eax, eax
jnz .a
pop edx
.b: add dl, "0"
call PrintCharacter
pop edx
cmp edx, 10
jb .b
pop ebx
ret

; ---------------------------------------------------------------------------

Title db 'Collatz Conjecture Disprover Unit - Googol Edition', 13, 10
db 10, 'Now verifying the number: 10 ^ ', 0
Title_ db ' + ...', 13, 10, 0
Error db 10, 10, 'Error: This number ', 0
Mirror db 39 dup '0', 13, 0
OneChar db 0
ALIGN 4
Screen dd Mirror+38
Bytes rd 1
Slots rd 3*(1+MaxDWords)

; -----------------------------------------------------------------------------

stack 4096

; ---------------------------------------------------------------------------

section '.idata' import data readable writeable

dd 0, 0, 0, rva kernel_name, rva kernel_table
dd 0, 0, 0, 0, 0

kernel_table:

ExitProcess dd rva _ExitProcess
WriteFile dd rva _WriteFile
GetStdHandle dd rva _GetStdHandle
dd 0

kernel_name db 'KERNEL32.DLL', 0

_ExitProcess dw 0
db 'ExitProcess', 0
_WriteFile dw 0
db 'WriteFile', 0
_GetStdHandle dw 0
db 'GetStdHandle', 0

; ---------------------------------------------------------------------------

section '.reloc' fixups data readable discardable









share|improve this question
























  • 0th suggestion: add a head comment what the code is about and where "the Collatz branch and steps" are coded. (Yes, for me, who can spot them as well as for yourself who knows what is what. In 2018…) most interested in speeding up [a piece of machine code] Specify a micro-architecture/implementation to target. Invest months of time in manufacturers instrumentation toolset.
    – greybeard
    37 mins ago


















0














The Wikipedia article about the Collatz Conjecture has these quotes:




If the conjecture is false, it can only be because there is some starting number which gives rise to a sequence that does not contain 1. Such a sequence might enter a repeating cycle that excludes 1, or increase without bound. No such sequence has been found.



... sometimes a conjecture's only counterexamples are found when using very large numbers.




The bit about using very large numbers motivated me to write the following Collatz calculator that uses Googol-sized numbers.

The program is very extensible. Just change the equates on top.



The faster the calculation, the more numbers can be verified for compliance, silently hoping for non-compliance of course...

I'm most interested in speeding up the CollatzEngine.



I display a running counter on screen just to prove that the program is still alive.



; Copyright (c) 2018, Sep Roland.
; All rights reserved.

PowerOfTen = 100 ;1 Googol == 10^100
MaxDWords = 12 ;1 Googol occupies 11 dwords
MaxSteps = 100000
Width = (1+MaxDWords)*4
STD_OUTPUT_HANDLE = 0FFFFFFF5h

format PE console

Start: mov esi, Title
call PrintString
mov eax, PowerOfTen
call PrintNumber
mov esi, Title_
call PrintString

mov ebx, Slots ;Pointing at SlotA
call BuildGoogol ; -> (EAX ECX..EBP)

Next: mov esi, [Screen] ;Update the counter on screen
call PrintString
call CollatzEngine ; -> ECX (EAX EDX..EDI)
call GoToNextNumber ; -> (EAX ESI)
jmp Next
; --------------------------------------
Fatal3: call Fatal ;From inside CollatzEngine
db "needs too many steps - Possible repetition!", 0
Fatal2: call Fatal ;From inside CollatzEngine
db "grows too big - Possible divergence!", 0
Fatal1: call Fatal ;From outside CollatzEngine
db "needs more space.", 0
Fatal: mov esi, Error
call PrintString
pop esi
call PrintString

mov al, 0
jmp TerminateProgram
; --------------------------------------
; IN (ebx) OUT () MOD (eax,ecx..ebp)
BuildGoogol:
mov ecx, 1
mov [ebx], ecx ;SignificantDWords = 1
mov [ebx+4], ecx ;SlotA = 1
mov ebp, PowerOfTen
jmp .c
.a: lea edi, [ebx+4] ;Current value * 10
xor esi, esi
mov ecx, [ebx] ;SignificantDWords
.b: mov eax, 10
mul dword [edi]
add eax, esi
adc edx, 0
stosd
mov esi, edx
dec ecx
jnz .b
test esi, esi
jz .c
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
mov [edi], esi
inc dword [ebx]
.c: dec ebp
jns .a
ret ;SlotA = 10 ^ #PowerOfTen
; --------------------------------------
; IN (ebx) OUT (ecx) MOD (eax,edx..edi)
CollatzEngine:
mov ecx, [ebx] ;SignificantDWords [1,MaxDWords]
inc ecx
mov esi, ebx
add ebx, Width ;(*) Within Collatz EBX points at SlotB
mov edi, ebx
rep movs dword [edi], [esi] ;Copy SlotA into SlotB

;;xor ecx, ecx ;StepCount
mov esi, [ebx] ;Cache SignificantDWords [1,MaxDWords]
jmp .Start

.Cont: mov eax, [ebx+4] ;Lowest dword of current number
bt eax, 0
adc ecx, 1 ;StepCount + [1,2]
cmp ecx, MaxSteps
ja Fatal3 ;"needs too many steps"

bt eax, 0
jnc @f
call .Odd ; -> ESI CF=0 (EAX EDX EDI)
@@: call .Even ; -> ESI (EAX EDX EDI)

.Start: cmp esi, 1
jne .Cont
cmp [ebx+4], esi
jne .Cont

.Done: mov [ebx], esi ;Un-cache SignificantDWords
sub ebx, Width ;(*) Restore EBX to point at SlotA
ret ;ECX is steps taken to reach 1
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=1) OUT (esi,CF=0) MOD (eax,edx,edi)
.Odd: lea edi, [ebx+Width+4] ;CF=1 This produces the +1
mov edx, esi
@@: mov eax, [edi-Width] ;n --> 2n+1
rcl eax, 1
stosd ;DST is intermediate storage (SlotC)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
mov [edi-Width], edx ;EDX=0
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0

@@: lea edi, [ebx+4] ;CF=0
mov edx, esi
@@: mov eax, [edi] ;2n+1 --> 3n+1
adc eax, [edi+Width]
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0
@@: ret
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=0) OUT (esi) MOD (eax,edx,edi)
.Even: lea edi, [ebx+esi*4] ;CF=0
mov edx, esi
std
@@: mov eax, [edi] ;n --> n/2
rcr eax, 1
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
cld
cmp [ebx+esi*4], edx ;EDX=0
sete dl ; -> EDX=[0,1]
sub esi, edx ;This is Downscale if EDX=1
ret
; --------------------------------------
; IN (ebx) OUT () MOD (eax,esi)
GoToNextNumber:
mov esi, ebx ;Increment number in SlotA
mov eax, [esi] ;SignificantDWords
.a: add esi, 4
add dword [esi], 1
jnc .b
dec eax
jnz .a
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
inc eax ; 0 -> 1
add [ebx], eax
mov [esi+4], eax

.b: lea esi, [Mirror+38] ;Increment counter in mirror
jmp .d
.c: sub al, 10
mov [esi], al
dec esi
cmp esi, [Screen]
jnb .d
mov [Screen], esi
.d: mov al, [esi]
add al, 1
cmp al, "9"
ja .c
mov [esi], al
ret
; --------------------------------------

; IN (al)
TerminateProgram:
movzx eax, al
push eax
call [ExitProcess]

; IN (esi)
PrintString:
push ebx
push esi ;(1)
push STD_OUTPUT_HANDLE
call [GetStdHandle]
mov ebx, eax
pop esi ;(1)
mov edi, esi
or ecx, -1
xor al, al
repne scasb
neg ecx
sub ecx, 2
push 0
push Bytes
push ecx
push esi
push ebx
call [WriteFile]
pop ebx
ret

; IN (dl)
PrintCharacter:
mov [OneChar], dl
push STD_OUTPUT_HANDLE
call [GetStdHandle]
push 0
push Bytes
push 1
push OneChar
push eax
call [WriteFile]
ret

; IN (eax)
PrintNumber:
push ebx
mov ebx, 10 ;CONST 10
push ebx ;Sentinel
.a: xor edx,edx
div ebx
push edx
test eax, eax
jnz .a
pop edx
.b: add dl, "0"
call PrintCharacter
pop edx
cmp edx, 10
jb .b
pop ebx
ret

; ---------------------------------------------------------------------------

Title db 'Collatz Conjecture Disprover Unit - Googol Edition', 13, 10
db 10, 'Now verifying the number: 10 ^ ', 0
Title_ db ' + ...', 13, 10, 0
Error db 10, 10, 'Error: This number ', 0
Mirror db 39 dup '0', 13, 0
OneChar db 0
ALIGN 4
Screen dd Mirror+38
Bytes rd 1
Slots rd 3*(1+MaxDWords)

; -----------------------------------------------------------------------------

stack 4096

; ---------------------------------------------------------------------------

section '.idata' import data readable writeable

dd 0, 0, 0, rva kernel_name, rva kernel_table
dd 0, 0, 0, 0, 0

kernel_table:

ExitProcess dd rva _ExitProcess
WriteFile dd rva _WriteFile
GetStdHandle dd rva _GetStdHandle
dd 0

kernel_name db 'KERNEL32.DLL', 0

_ExitProcess dw 0
db 'ExitProcess', 0
_WriteFile dw 0
db 'WriteFile', 0
_GetStdHandle dw 0
db 'GetStdHandle', 0

; ---------------------------------------------------------------------------

section '.reloc' fixups data readable discardable









share|improve this question
























  • 0th suggestion: add a head comment what the code is about and where "the Collatz branch and steps" are coded. (Yes, for me, who can spot them as well as for yourself who knows what is what. In 2018…) most interested in speeding up [a piece of machine code] Specify a micro-architecture/implementation to target. Invest months of time in manufacturers instrumentation toolset.
    – greybeard
    37 mins ago
















0












0








0







The Wikipedia article about the Collatz Conjecture has these quotes:




If the conjecture is false, it can only be because there is some starting number which gives rise to a sequence that does not contain 1. Such a sequence might enter a repeating cycle that excludes 1, or increase without bound. No such sequence has been found.



... sometimes a conjecture's only counterexamples are found when using very large numbers.




The bit about using very large numbers motivated me to write the following Collatz calculator that uses Googol-sized numbers.

The program is very extensible. Just change the equates on top.



The faster the calculation, the more numbers can be verified for compliance, silently hoping for non-compliance of course...

I'm most interested in speeding up the CollatzEngine.



I display a running counter on screen just to prove that the program is still alive.



; Copyright (c) 2018, Sep Roland.
; All rights reserved.

PowerOfTen = 100 ;1 Googol == 10^100
MaxDWords = 12 ;1 Googol occupies 11 dwords
MaxSteps = 100000
Width = (1+MaxDWords)*4
STD_OUTPUT_HANDLE = 0FFFFFFF5h

format PE console

Start: mov esi, Title
call PrintString
mov eax, PowerOfTen
call PrintNumber
mov esi, Title_
call PrintString

mov ebx, Slots ;Pointing at SlotA
call BuildGoogol ; -> (EAX ECX..EBP)

Next: mov esi, [Screen] ;Update the counter on screen
call PrintString
call CollatzEngine ; -> ECX (EAX EDX..EDI)
call GoToNextNumber ; -> (EAX ESI)
jmp Next
; --------------------------------------
Fatal3: call Fatal ;From inside CollatzEngine
db "needs too many steps - Possible repetition!", 0
Fatal2: call Fatal ;From inside CollatzEngine
db "grows too big - Possible divergence!", 0
Fatal1: call Fatal ;From outside CollatzEngine
db "needs more space.", 0
Fatal: mov esi, Error
call PrintString
pop esi
call PrintString

mov al, 0
jmp TerminateProgram
; --------------------------------------
; IN (ebx) OUT () MOD (eax,ecx..ebp)
BuildGoogol:
mov ecx, 1
mov [ebx], ecx ;SignificantDWords = 1
mov [ebx+4], ecx ;SlotA = 1
mov ebp, PowerOfTen
jmp .c
.a: lea edi, [ebx+4] ;Current value * 10
xor esi, esi
mov ecx, [ebx] ;SignificantDWords
.b: mov eax, 10
mul dword [edi]
add eax, esi
adc edx, 0
stosd
mov esi, edx
dec ecx
jnz .b
test esi, esi
jz .c
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
mov [edi], esi
inc dword [ebx]
.c: dec ebp
jns .a
ret ;SlotA = 10 ^ #PowerOfTen
; --------------------------------------
; IN (ebx) OUT (ecx) MOD (eax,edx..edi)
CollatzEngine:
mov ecx, [ebx] ;SignificantDWords [1,MaxDWords]
inc ecx
mov esi, ebx
add ebx, Width ;(*) Within Collatz EBX points at SlotB
mov edi, ebx
rep movs dword [edi], [esi] ;Copy SlotA into SlotB

;;xor ecx, ecx ;StepCount
mov esi, [ebx] ;Cache SignificantDWords [1,MaxDWords]
jmp .Start

.Cont: mov eax, [ebx+4] ;Lowest dword of current number
bt eax, 0
adc ecx, 1 ;StepCount + [1,2]
cmp ecx, MaxSteps
ja Fatal3 ;"needs too many steps"

bt eax, 0
jnc @f
call .Odd ; -> ESI CF=0 (EAX EDX EDI)
@@: call .Even ; -> ESI (EAX EDX EDI)

.Start: cmp esi, 1
jne .Cont
cmp [ebx+4], esi
jne .Cont

.Done: mov [ebx], esi ;Un-cache SignificantDWords
sub ebx, Width ;(*) Restore EBX to point at SlotA
ret ;ECX is steps taken to reach 1
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=1) OUT (esi,CF=0) MOD (eax,edx,edi)
.Odd: lea edi, [ebx+Width+4] ;CF=1 This produces the +1
mov edx, esi
@@: mov eax, [edi-Width] ;n --> 2n+1
rcl eax, 1
stosd ;DST is intermediate storage (SlotC)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
mov [edi-Width], edx ;EDX=0
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0

@@: lea edi, [ebx+4] ;CF=0
mov edx, esi
@@: mov eax, [edi] ;2n+1 --> 3n+1
adc eax, [edi+Width]
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0
@@: ret
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=0) OUT (esi) MOD (eax,edx,edi)
.Even: lea edi, [ebx+esi*4] ;CF=0
mov edx, esi
std
@@: mov eax, [edi] ;n --> n/2
rcr eax, 1
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
cld
cmp [ebx+esi*4], edx ;EDX=0
sete dl ; -> EDX=[0,1]
sub esi, edx ;This is Downscale if EDX=1
ret
; --------------------------------------
; IN (ebx) OUT () MOD (eax,esi)
GoToNextNumber:
mov esi, ebx ;Increment number in SlotA
mov eax, [esi] ;SignificantDWords
.a: add esi, 4
add dword [esi], 1
jnc .b
dec eax
jnz .a
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
inc eax ; 0 -> 1
add [ebx], eax
mov [esi+4], eax

.b: lea esi, [Mirror+38] ;Increment counter in mirror
jmp .d
.c: sub al, 10
mov [esi], al
dec esi
cmp esi, [Screen]
jnb .d
mov [Screen], esi
.d: mov al, [esi]
add al, 1
cmp al, "9"
ja .c
mov [esi], al
ret
; --------------------------------------

; IN (al)
TerminateProgram:
movzx eax, al
push eax
call [ExitProcess]

; IN (esi)
PrintString:
push ebx
push esi ;(1)
push STD_OUTPUT_HANDLE
call [GetStdHandle]
mov ebx, eax
pop esi ;(1)
mov edi, esi
or ecx, -1
xor al, al
repne scasb
neg ecx
sub ecx, 2
push 0
push Bytes
push ecx
push esi
push ebx
call [WriteFile]
pop ebx
ret

; IN (dl)
PrintCharacter:
mov [OneChar], dl
push STD_OUTPUT_HANDLE
call [GetStdHandle]
push 0
push Bytes
push 1
push OneChar
push eax
call [WriteFile]
ret

; IN (eax)
PrintNumber:
push ebx
mov ebx, 10 ;CONST 10
push ebx ;Sentinel
.a: xor edx,edx
div ebx
push edx
test eax, eax
jnz .a
pop edx
.b: add dl, "0"
call PrintCharacter
pop edx
cmp edx, 10
jb .b
pop ebx
ret

; ---------------------------------------------------------------------------

Title db 'Collatz Conjecture Disprover Unit - Googol Edition', 13, 10
db 10, 'Now verifying the number: 10 ^ ', 0
Title_ db ' + ...', 13, 10, 0
Error db 10, 10, 'Error: This number ', 0
Mirror db 39 dup '0', 13, 0
OneChar db 0
ALIGN 4
Screen dd Mirror+38
Bytes rd 1
Slots rd 3*(1+MaxDWords)

; -----------------------------------------------------------------------------

stack 4096

; ---------------------------------------------------------------------------

section '.idata' import data readable writeable

dd 0, 0, 0, rva kernel_name, rva kernel_table
dd 0, 0, 0, 0, 0

kernel_table:

ExitProcess dd rva _ExitProcess
WriteFile dd rva _WriteFile
GetStdHandle dd rva _GetStdHandle
dd 0

kernel_name db 'KERNEL32.DLL', 0

_ExitProcess dw 0
db 'ExitProcess', 0
_WriteFile dw 0
db 'WriteFile', 0
_GetStdHandle dw 0
db 'GetStdHandle', 0

; ---------------------------------------------------------------------------

section '.reloc' fixups data readable discardable









share|improve this question















The Wikipedia article about the Collatz Conjecture has these quotes:




If the conjecture is false, it can only be because there is some starting number which gives rise to a sequence that does not contain 1. Such a sequence might enter a repeating cycle that excludes 1, or increase without bound. No such sequence has been found.



... sometimes a conjecture's only counterexamples are found when using very large numbers.




The bit about using very large numbers motivated me to write the following Collatz calculator that uses Googol-sized numbers.

The program is very extensible. Just change the equates on top.



The faster the calculation, the more numbers can be verified for compliance, silently hoping for non-compliance of course...

I'm most interested in speeding up the CollatzEngine.



I display a running counter on screen just to prove that the program is still alive.



; Copyright (c) 2018, Sep Roland.
; All rights reserved.

PowerOfTen = 100 ;1 Googol == 10^100
MaxDWords = 12 ;1 Googol occupies 11 dwords
MaxSteps = 100000
Width = (1+MaxDWords)*4
STD_OUTPUT_HANDLE = 0FFFFFFF5h

format PE console

Start: mov esi, Title
call PrintString
mov eax, PowerOfTen
call PrintNumber
mov esi, Title_
call PrintString

mov ebx, Slots ;Pointing at SlotA
call BuildGoogol ; -> (EAX ECX..EBP)

Next: mov esi, [Screen] ;Update the counter on screen
call PrintString
call CollatzEngine ; -> ECX (EAX EDX..EDI)
call GoToNextNumber ; -> (EAX ESI)
jmp Next
; --------------------------------------
Fatal3: call Fatal ;From inside CollatzEngine
db "needs too many steps - Possible repetition!", 0
Fatal2: call Fatal ;From inside CollatzEngine
db "grows too big - Possible divergence!", 0
Fatal1: call Fatal ;From outside CollatzEngine
db "needs more space.", 0
Fatal: mov esi, Error
call PrintString
pop esi
call PrintString

mov al, 0
jmp TerminateProgram
; --------------------------------------
; IN (ebx) OUT () MOD (eax,ecx..ebp)
BuildGoogol:
mov ecx, 1
mov [ebx], ecx ;SignificantDWords = 1
mov [ebx+4], ecx ;SlotA = 1
mov ebp, PowerOfTen
jmp .c
.a: lea edi, [ebx+4] ;Current value * 10
xor esi, esi
mov ecx, [ebx] ;SignificantDWords
.b: mov eax, 10
mul dword [edi]
add eax, esi
adc edx, 0
stosd
mov esi, edx
dec ecx
jnz .b
test esi, esi
jz .c
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
mov [edi], esi
inc dword [ebx]
.c: dec ebp
jns .a
ret ;SlotA = 10 ^ #PowerOfTen
; --------------------------------------
; IN (ebx) OUT (ecx) MOD (eax,edx..edi)
CollatzEngine:
mov ecx, [ebx] ;SignificantDWords [1,MaxDWords]
inc ecx
mov esi, ebx
add ebx, Width ;(*) Within Collatz EBX points at SlotB
mov edi, ebx
rep movs dword [edi], [esi] ;Copy SlotA into SlotB

;;xor ecx, ecx ;StepCount
mov esi, [ebx] ;Cache SignificantDWords [1,MaxDWords]
jmp .Start

.Cont: mov eax, [ebx+4] ;Lowest dword of current number
bt eax, 0
adc ecx, 1 ;StepCount + [1,2]
cmp ecx, MaxSteps
ja Fatal3 ;"needs too many steps"

bt eax, 0
jnc @f
call .Odd ; -> ESI CF=0 (EAX EDX EDI)
@@: call .Even ; -> ESI (EAX EDX EDI)

.Start: cmp esi, 1
jne .Cont
cmp [ebx+4], esi
jne .Cont

.Done: mov [ebx], esi ;Un-cache SignificantDWords
sub ebx, Width ;(*) Restore EBX to point at SlotA
ret ;ECX is steps taken to reach 1
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=1) OUT (esi,CF=0) MOD (eax,edx,edi)
.Odd: lea edi, [ebx+Width+4] ;CF=1 This produces the +1
mov edx, esi
@@: mov eax, [edi-Width] ;n --> 2n+1
rcl eax, 1
stosd ;DST is intermediate storage (SlotC)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
mov [edi-Width], edx ;EDX=0
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0

@@: lea edi, [ebx+4] ;CF=0
mov edx, esi
@@: mov eax, [edi] ;2n+1 --> 3n+1
adc eax, [edi+Width]
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
jnc @f
cmp esi, MaxDWords ;Upscale
jnb Fatal2 ;"grows too big"
inc edx ; 0 -> 1
mov [edi], edx
add esi, edx ; -> CF=0
@@: ret
; - - - - - - - - - - - - - - - - - - -
; IN (ebx,esi,CF=0) OUT (esi) MOD (eax,edx,edi)
.Even: lea edi, [ebx+esi*4] ;CF=0
mov edx, esi
std
@@: mov eax, [edi] ;n --> n/2
rcr eax, 1
stosd ;DST is intermediate storage (SlotB)
dec edx
jnz @b
cld
cmp [ebx+esi*4], edx ;EDX=0
sete dl ; -> EDX=[0,1]
sub esi, edx ;This is Downscale if EDX=1
ret
; --------------------------------------
; IN (ebx) OUT () MOD (eax,esi)
GoToNextNumber:
mov esi, ebx ;Increment number in SlotA
mov eax, [esi] ;SignificantDWords
.a: add esi, 4
add dword [esi], 1
jnc .b
dec eax
jnz .a
cmp dword [ebx], MaxDWords ;Upscale
jnb Fatal1 ;"needs more space"
inc eax ; 0 -> 1
add [ebx], eax
mov [esi+4], eax

.b: lea esi, [Mirror+38] ;Increment counter in mirror
jmp .d
.c: sub al, 10
mov [esi], al
dec esi
cmp esi, [Screen]
jnb .d
mov [Screen], esi
.d: mov al, [esi]
add al, 1
cmp al, "9"
ja .c
mov [esi], al
ret
; --------------------------------------

; IN (al)
TerminateProgram:
movzx eax, al
push eax
call [ExitProcess]

; IN (esi)
PrintString:
push ebx
push esi ;(1)
push STD_OUTPUT_HANDLE
call [GetStdHandle]
mov ebx, eax
pop esi ;(1)
mov edi, esi
or ecx, -1
xor al, al
repne scasb
neg ecx
sub ecx, 2
push 0
push Bytes
push ecx
push esi
push ebx
call [WriteFile]
pop ebx
ret

; IN (dl)
PrintCharacter:
mov [OneChar], dl
push STD_OUTPUT_HANDLE
call [GetStdHandle]
push 0
push Bytes
push 1
push OneChar
push eax
call [WriteFile]
ret

; IN (eax)
PrintNumber:
push ebx
mov ebx, 10 ;CONST 10
push ebx ;Sentinel
.a: xor edx,edx
div ebx
push edx
test eax, eax
jnz .a
pop edx
.b: add dl, "0"
call PrintCharacter
pop edx
cmp edx, 10
jb .b
pop ebx
ret

; ---------------------------------------------------------------------------

Title db 'Collatz Conjecture Disprover Unit - Googol Edition', 13, 10
db 10, 'Now verifying the number: 10 ^ ', 0
Title_ db ' + ...', 13, 10, 0
Error db 10, 10, 'Error: This number ', 0
Mirror db 39 dup '0', 13, 0
OneChar db 0
ALIGN 4
Screen dd Mirror+38
Bytes rd 1
Slots rd 3*(1+MaxDWords)

; -----------------------------------------------------------------------------

stack 4096

; ---------------------------------------------------------------------------

section '.idata' import data readable writeable

dd 0, 0, 0, rva kernel_name, rva kernel_table
dd 0, 0, 0, 0, 0

kernel_table:

ExitProcess dd rva _ExitProcess
WriteFile dd rva _WriteFile
GetStdHandle dd rva _GetStdHandle
dd 0

kernel_name db 'KERNEL32.DLL', 0

_ExitProcess dw 0
db 'ExitProcess', 0
_WriteFile dw 0
db 'WriteFile', 0
_GetStdHandle dw 0
db 'GetStdHandle', 0

; ---------------------------------------------------------------------------

section '.reloc' fixups data readable discardable






performance algorithm assembly collatz-sequence x86






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 43 mins ago









200_success

128k15150412




128k15150412










asked 2 hours ago









Sep Roland

1,923617




1,923617












  • 0th suggestion: add a head comment what the code is about and where "the Collatz branch and steps" are coded. (Yes, for me, who can spot them as well as for yourself who knows what is what. In 2018…) most interested in speeding up [a piece of machine code] Specify a micro-architecture/implementation to target. Invest months of time in manufacturers instrumentation toolset.
    – greybeard
    37 mins ago




















  • 0th suggestion: add a head comment what the code is about and where "the Collatz branch and steps" are coded. (Yes, for me, who can spot them as well as for yourself who knows what is what. In 2018…) most interested in speeding up [a piece of machine code] Specify a micro-architecture/implementation to target. Invest months of time in manufacturers instrumentation toolset.
    – greybeard
    37 mins ago


















0th suggestion: add a head comment what the code is about and where "the Collatz branch and steps" are coded. (Yes, for me, who can spot them as well as for yourself who knows what is what. In 2018…) most interested in speeding up [a piece of machine code] Specify a micro-architecture/implementation to target. Invest months of time in manufacturers instrumentation toolset.
– greybeard
37 mins ago






0th suggestion: add a head comment what the code is about and where "the Collatz branch and steps" are coded. (Yes, for me, who can spot them as well as for yourself who knows what is what. In 2018…) most interested in speeding up [a piece of machine code] Specify a micro-architecture/implementation to target. Invest months of time in manufacturers instrumentation toolset.
– greybeard
37 mins ago

















active

oldest

votes











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210608%2fcollatz-conjecture-disprover-unit-googol-edition%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210608%2fcollatz-conjecture-disprover-unit-googol-edition%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Morgemoulin

Scott Moir

Souastre