Sunday, January 27, 2013
Wednesday, March 09, 2011
Saturday, December 15, 2007
For me the most fasinating thing about the Collatz Conjecture is how it so blantantly points to a deficiency in mathematics. It seems incredibly obvious that it is true. The problem lies in a way to say that no loops are created excluding one - a limited understanding of process dynamics.
Recently, I've changed the problem to eliminate the split condition - there is no reason to divide even numbers by two. Without the split we have a simplified algorithm, but it must work with larger numbers. This doesn't seem like an intuitive step.
1. y <= 1+Shr[Xor[x,x-1],1]
2. if x=y then step 5
3. x <= 3x + y
4. goto step 1
5. number is a power of two
The first step calculates the value of least set bit. Instead of dividing by two, one is scaled up to match the bit which would make (x) odd if it were down scaled. Only when a single bit is set does the algorithm end (step 2). (y) can be tracked progressively instead of looking at the complete representation of (x) as step 3 always clears the least set bit (or more). Of course, I've coded this in x86:
; check Collatz Conjecture on multi-percision numberTry a really big number - like 2^131072 + 3
; carry flag set on array overflow
; carry flag clear on pass
; (otherwise it loops forever: not likely, but hasn't been proven)
; NOTE: array should be twice the size of number to test - too large
; is not a problem as only active bits are operated on.
label .arr at esp+4+32 ; BigInt
label .len at esp+8+32 ; length (dwords)
; address past number in EDI (active end marker)
; (need at least one zero dword on end!)
.z: dec eax
test dword [ebx+eax*4],-1
; advance to lowest set bit
.0: test [esi],edx
.0a: rol edx,1
jnc .0 ; HINT: taken
cmp esi,ebp ; end
cmovnc esi,ebx ; reset
; ESI[ECX] is first set bit, multiply by three and add ESI[ECX]
; all (virtual) lower bits are zero.
; test if buffer is == ESI[ECX] then done!
jne .kx ; HINT: taken
; if EDI==ESI+4 or (ESI+4==EBP && EDI==EBX)
; (faster than testing all of buffer)
mul dword [esi]
cmp esi,ebp ; end
cmovnc esi,ebx ; reset
cmp edi,ebp ; end
cmovnc edi,ebx ; reset
.5: pop esi
jmp .0a ; we just cleared that bit
TestBuffer rb 32*1024 ; zero bytesWhy is this important? The algorithm is no longer concerned with value of (x) except for the exit condition - the same operation takes place each loop. It is sufficient to show that (y) -> (x) for all (x), and the conjecture is true. The multiplication by three is irrelavant because the addition propells the least set bit at a rate greater than the constant multiple!
mov dword [TestBuffer],3
mov dword [TestBuffer+16*1024],1
push 32*1024/4 ; L1 cache size (c:
; 3829ms on my machine
Status of the 3x+1 class record progress as of: Dec 13, 2007. Intervals areBasically, a trillion per day, per Ghz.
indicated in blocks of 20,000,000,000,000 (20 E+12 or 20 trillion numbers).
Calculation of a single block takes approximately 20 days of (idle) time on a
Pentium 1000 MHz.
Naturally, I'm currious how my routine compares:
Currently, they are working on 7 * 2^53 block of numbers. I ran a test of my algorithm for 2^24 numbers (in that block range) which took 38781ms. Which means it is roughly 25 times slower. Their algorithm is tuned for this size and uses large data structures (to avoid processing numbers). I might be able to double the speed of my algorithm, but confirming ranges of numbers is not what it's designed for.
Sunday, November 11, 2007
There is also a bit of irony in irrational numbers. Mathematics was first designed to track finances and military forces in an attempt to add great stablity. Imagine the surprise when even the simiplest of systems could produce absolute chaos and uncertainty.
Pi(π) is the most famous irrational number and countless lifetimes have been spent in it's study and popularization. Yesterday I spent a couple hours devising an x86 version of the BBP algorithm:
; NOTE: This isn't the fastest way to compute pi approximations.(FASM Syntax)
; TESTING STATUS:
; confirmed valid for all input [0,10000]
; digit time (1.6Ghz Dothan)
; 10^4 16 ms
; 10^5 219 ms
; 10^6 2860 ms 6C65D566
; 10^7 33938 ms
; 10^8 407828 ms
; Pi hex digit extraction:
; 243F6 A8885 A308D 31319 8A2E0 37073 44A40 93822
; 299F3 1D008 2EFA9 8EC4E 6C894 52821 E638D 01377
; 16^EBP MOD ECX=8k+z
; Special cases:
; EBP=0, return 1
; ECX=1, return 0
; EDX is return value
mpow: xor edx,edx
.0: mul eax
.1: bt ebp,ebx
.2: dec ebx
mov eax, edx
xor edi,edi ; fraction
.1: call mpow ; 16^EBP mod ECX
div ecx ; EDX:0 / 8k+m
add ecx,8 ; 8k+m, k[0,EBP]
.2: mov eax,ebp
invoke PiHexDigit, 1000000
Tuesday, October 30, 2007
It didn't even seem that difficult, really. My first two tries were completely from my gut. One was a brute force stab with sorting in one dimension: usually these attempts just help me get a feel for the problem. With 5000 lines that means over 12 million intersection test - sorting and early exit dropped it down to about 4 million. Certainly within range of brute forcing on modern processors.
The intersection test itself seemed to be problem. So, I used a little topology to devise a test based strictly on triangle area, given the connected graph of the four points. Got a different result, but it was close enough to the last one to give a sense of accomplishment. (It's really fast and merits further research.)
Where could the problem be? I searched the web for algorithms - seems line sweeping is all the rage. Quickly, I plugged a couple different intersection tests into my first attempt. Two more different answers!
Have to put the problem aside for now...
Friday, October 19, 2007
I created a macro in MASM to ease direct access to the random array:
mov ebp, PRNG_CA_Pasqualoni_StateWidth / 4Here the random data is stored in EAX, and EBP indexes into the array. If using a register to index into the array seems like a bad idea then try to write a function with less overhead than load/storing a register. The intent is to churn through a massive number of random integers.
_0: PRNG_CA_Pasqualoni eax, ebp
; (do somthing with random data)
jXX _0 ; until exit condition reached
The features of MASM have been used to encapsulate the routine within an object module. Although the code is not lengthy it demonstrates coding techniques which make code reusable and easy to understand. The interface is described in a concise way within the include file - there is no need to look at the code to use the functions. Following the defined interface allows the code to operate in a transparent way. Within the assembly file all the nuances are explained making modification in the future less error prone. The file is small enough to fit on a couple screens of text and be quickly comprehended.
(Below is my MASM conversion.)