Sunday, January 27, 2013

Still alive and coding...

Al Zimmermann has a new contest. Always fun to flex one's wits. Give it a try:

http://azspcs.net/Contest/Factorials

Wednesday, March 09, 2011

Automata Captcha Idea

http://demonstrations.wolfram.com/TexturePerceptionPatterns/

Seeing this demonstration reminded me of a captcha idea I had a few years ago. The human user would need to define the image outline they perceived. bitRAKE.com got hacked so I stopped work on the PHP code, and had almost forgotten about it.

Saturday, December 15, 2007

Collatz Conjecture

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 number
;
; 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.
CollatzArrayQ:
label .arr at esp+4+32 ; BigInt
label .len at esp+8+32 ; length (dwords)

pushad
mov ebx,[.arr]
mov eax,[.len]
mov edx,1
mov esi,ebx
lea ebp,[ebx+eax*4]
; 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
je .z
lea edi,[ebx+eax*4+4]
cmp edi,ebp
je .over

; advance to lowest set bit
.0: test [esi],edx
jne .1
.0a: rol edx,1
jnc .0 ; HINT: taken
add esi,4
cmp esi,ebp ; end
cmovnc esi,ebx ; reset
jmp .0
; ESI[ECX] is first set bit, multiply by three and add ESI[ECX]
; all (virtual) lower bits are zero.
.1:
; test if buffer is == ESI[ECX] then done!
cmp [esi],edx
jne .kx ; HINT: taken
; if EDI==ESI+4 or (ESI+4==EBP && EDI==EBX)
; (faster than testing all of buffer)
mov ecx,edi
lea eax,[esi+4]
cmp edi,ebx
cmove ecx,ebp
cmp eax,ecx
je .x
.kx:
push edx
push esi
.2:
mov eax,3
mov ecx,edx
mul dword [esi]
add eax,ecx
adc edx,0
mov [esi],eax

add esi,4
cmp esi,ebp ; end
cmovnc esi,ebx ; reset

cmp esi,edi
jne .2

test edx,edx
je .5

cmp edi,[esp]
je .over
mov [edi],edx
add edi,4
cmp edi,ebp ; end
cmovnc edi,ebx ; reset

.5: pop esi
pop edx
jmp .0a ; we just cleared that bit

.x: popad
clc
retn 8

.over: popad
stc
retn 8
Try a really big number - like 2^131072 + 3

TestBuffer rb 32*1024 ; zero bytes

mov dword [TestBuffer],3
mov dword [TestBuffer+16*1024],1

push 32*1024/4 ; L1 cache size (c:
push TestBuffer1
call CollatzArrayQ
; 3829ms on my machine
Why 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!

(c:

Update:

Status of the 3x+1 class record progress as of: Dec 13, 2007. Intervals are
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.
Basically, a trillion per day, per Ghz.

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

Slices of Weekend Pi

Irrational numbers seem to have their hooks into nature somehow. Clearly, they are the product of something fundamental, but I think they also point out limits in the way we represent ideas. The really special ones get a symbol that we use without regard for the unique abundance they represent.

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.
;
; 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:
;3.
; 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
cmp ecx,1
je .x
bsr ebx,ebp
mov edx,1
jne .1
.x: retn

.0: mul eax
div ecx
.1: bt ebp,ebx
mov eax,16
jnc .2
mul edx
div ecx
.2: dec ebx
mov eax, edx
jns .0
retn

series:
xor edi,edi ; fraction
.1: call mpow ; 16^EBP mod ECX
xor eax,eax
div ecx ; EDX:0 / 8k+m
add ecx,8 ; 8k+m, k[0,EBP]
add edi,eax
dec ebp
jns .1

mov ebp,10000000h
.2: mov eax,ebp
xor edx,edx
div ecx
add ecx,8
shr ebp,4
cmp ecx,ebp
lea edi,[edi+eax]
jna .2
retn

PiHex:
pushad
mov ebp,[esp+36]
mov ecx,1
call series
lea esi,[edi*4]

mov ebp,[esp+36]
mov ecx,4
call series
sub esi,edi
sub esi,edi

mov ebp,[esp+36]
mov ecx,5
call series
sub esi,edi

mov ebp,[esp+36]
mov ecx,6
call series
sub esi,edi
mov [esp+28],esi
popad
retn 4


invoke PiHexDigit, 1000000
(FASM Syntax)

Tuesday, October 30, 2007

Crossing Segment Intersections

I've been away from Project Euler for several months, and decided to try some of the new problems for fun. Not being shy about a challenge I just chose the most recent one. Couple hours and implementations later, and the solution remains out of reach.

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

An Improvement to Random

Recently, I stumbled upon another PRNG (pseudo-random number generator) which had some very unique properties. Not only does the generator score high on tests, but functionally the operations transfer easily into a compact set of instructions - making it very fast. Based on a rather large cellular automata, I didn't think it would be faster than Steven Wolfram's Rule 30 (used in Mathematica for RandomInteger[]); but the byte granularity of the 1D automata reduces to three loads, an add, and a store for each byte. No multiply, division, long dependancy chain, nor multiple passes. Furthermore, if a large random list is updated only when all the values have been used further speed is gained.

I created a macro in MASM to ease direct access to the random array:

    mov ebp, PRNG_CA_Pasqualoni_StateWidth / 4
_0: PRNG_CA_Pasqualoni eax, ebp
; (do somthing with random data)
jXX _0 ; until exit condition reached
Here 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.

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.)