Category : C Source Code
Archive   : FRAC151S.ZIP
Filename : NEWTON.ASM

 
Output of file : NEWTON.ASM contained in archive : FRAC151S.ZIP

; NEWTON.ASM : Procedure NewtonFractal() from FRACTINT.
; Lee Daniel Crocker, 4/23/89.
;
; Tabs: 8
;
; Modifications:
; BT = Bert Tyler
; TW = Timothy Wegner
; RD = Robert Day
; MP = Mark Peterson
;
; Note: newton.asm was totally rewritten by Lee Crocker for FRACTINT 10.0
; for integration with the newly structured fractal engine in calcmand.c
; and fractals.c. The current routine consists of the inner orbit
; calculation, with the supporting code removed. Early versions of
; newton.asm contained a complete newton fractal function.
;
; Assembled by Microsoft Macro Assembler 5.1, for use with Microsoft C 5.1.
;

; Required for compatibility if Turbo ASM (BT 5/20/89)

IFDEF ??version
MASM51
QUIRKS
EMUL
ENDIF

.model medium, c

public NewtonFractal2
public invertz2

.data
extrn color:word, maxcolor:word, degree:word, basin:word
extrn row:word, col:word

extrn dx0:dword, dy0:dword
extrn dx1:dword, dy1:dword

extrn old:qword, new:qword, d1overd:qword, roverd:qword
extrn threshold:qword, floatmin:qword, floatmax:qword
extrn f_radius:qword, f_xcenter:qword, f_ycenter:qword
extrn roots:word, tempsqrx:qword

statw dw ?

.code

public NewtonFractal2
NewtonFractal2 proc

;
; cpower(&old, degree-1, &tmp)
;
mov ax, degree
dec ax

fld old + 8
fld old
;
; cpower() is expanded inline here.
;
shr ax, 1
jnc load1 ; if (exp & 1)

fld st(1)
fld st(1)
jmp short looptop ; tmp = old
load1:
fldz
fld1 ; else tmp = [1,0]
looptop:
cmp ax, 0
je loopexit ; while (exp)

fld st(2) ; RD 5/7/89: Calculate xt^2 - yt^2
fadd st, st(4) ; by using (xt+yt)*(xt-yt), which
fld st(3) ; trades one multiplication for an
fsub st, st(5) ; addition. This trick saves a
fmul ; whopping 1.2% of time.

fld st(4)
fmul st, st(4)
fadd st, st ; yt = 2 * xt * yt

fstp st(5) ; tmp.y = yt
fstp st(3) ; tmp.x = xt

shr ax, 1
jnc looptop ; if (exp & 1)

fld st(2)
fmul st, st(1)
fld st(4)
fmul st, st(3)
fsub ; tmp.x = xt * tmp.x - yt * tmp.y

fld st(3)
fmul st, st(3)
fld st(5)
fmul st, st(3)
fadd ; tmp.y = xt * tmp.y + yt * tmp.x
fstp st(3)
fstp st(1)

jmp short looptop
loopexit:
fstp st(2)
fstp st(2)
;
; End of complex_power() routine. Result is in ST, ST(1)
;
;
; complex_mult(tmp, old, &new);
;
fld old + 8
fld old

fld st(3) ; tmp.y
fmul st, st(1) ; old.x
fld st(3) ; tmp.x
fmul st, st(3) ; old.y
fadd
fld st(3) ; tmp.x
fmul st, st(2) ; old.x
fld st(5) ; tmp.y
fmul st, st(4) ; old.y
fsub
;
; if (DIST1(new) < THRESHOLD) {
;
fld1
fsubr st, st(1)
fmul st, st
fld st(2) ; new.y
fmul st, st
fadd
fcomp threshold
fstsw statw
mov ax, statw
sahf
jnc notless
;
; if (fractype == NEWTBASIN) {
;
mov ax, basin
cmp ax, 0
je notbasin

mov bx, roots
mov dx, -1 ; tempcolor = -1
sub cx, cx
dloop:
fld qword ptr [bx] ; roots[i].x
fsub st, st(3) ; old.x
fmul st, st
fld qword ptr [bx+8]; roots[i].y
fsub st, st(5) ; old.y
fmul st, st
fadd
fcomp threshold
fstsw statw
mov ax, statw
sahf ; if (distance(roots[i],old) < threshold)...
jnc nl2

; TW commented out next few lines and add dx,ax to eliminate newtbasin
; color shades per Phil Wilson's request 12/03/89

; TW put it back in in response to another use as an option! 7/7/90
mov dx, cx
cmp basin,2 ; basin==2 is flag for stripes
jne nostripes
mov ax, color
and ax, 1
shl ax, 1
shl ax, 1
shl ax, 1

and dx, 7
add dx, ax
nostripes:
inc dx ; tempcolor = 1+(i&7)+((color&1)<<3)
jmp short nfb ; break
nl2:
add bx, 16
inc cx
cmp cx, degree
jl dloop
nfb:
mov ax, dx
cmp dx, -1
jne notm1
mov ax, maxcolor ; if (tmpcolor == -1)...
notm1:
mov color, ax
notbasin:
mov ax, 1
jmp nlexit
notless:
fld d1overd
fmul st(2), st ; new.y *= d1overd
fmul
fld roverd
fadd ; new.x = d1overd * new.x + roverd

fld st(5) ; tmp.y
fmul st, st
fld st(5) ; tmp.x
fmul st, st
fadd
fcom floatmin
fstsw statw
mov ax, statw
sahf ; if (mod(tmp) < FLT_MIN) {
jnc cont
mov ax, 1
fstp st
jmp nlexit
cont:
fld1
fdivr
fst st(4) ; old.y
fstp st(3) ; old.x

fld st(4) ; tmp.x
fmul st, st(1) ; new.x
fld st(6) ; tmp.y
fmul st, st(3) ; new.y
fadd
fmulp st(3), st ; old.x

fld st(4) ; tmp.x
fmul st, st(2) ; new.y
fld st(6) ; tmp.y
fmul st, st(2) ; new.x
fsub
fmulp st(4), st ; old.y ; old = new / tmp

; MP Orbit Bug Fix 11/1/90
; fstp new
; fstp new + 8
; fstp old
; fstp old + 8
fstp st
fstp st
fst new
fstp old
fst new + 8
fstp old + 8

mov ax, 0
jmp nlx2

nlexit:

;MP Orbit Bug Fix 11/1/90
; fstp new
; fstp new + 8
fstp st
fstp st
fstp new
fstp new + 8

nlx2:
fstp st
fstp st

ret
NewtonFractal2 endp
;
;
;
public invertz2
invertz2 proc uses si, zval:word ; TW 11/03/89 changed zval to near

fld f_xcenter
fld f_ycenter

mov bx, col
shl bx, 1
shl bx, 1
shl bx, 1

mov cx, row
shl cx, 1
shl cx, 1
shl cx, 1

mov ax, ds
lds si, dx0
add si, bx
fld qword ptr [si]
mov ds, ax
lds si, dx1
add si, cx
fld qword ptr [si]
fadd
fsub st, st(2)

mov ds, ax
lds si, dy0
add si, cx
fld qword ptr [si]
mov ds, ax
lds si, dy1
add si, bx
fld qword ptr [si]
fadd
fsub st, st(2)

mov ds, ax
fld st(1)
fmul st, st
fld st(1)
fmul st, st
fadd

fcom floatmin
fstsw statw
mov ax, statw
sahf
jnc inl1

fstp st
fld floatmax
jmp icom
inl1:
fld f_radius
fdivr
icom:
fst tempsqrx

fmul st(2), st
fmul
faddp st(2), st
faddp st(2), st

; lds si, zval ; TW 11/03/89 zval is now a near pointer
mov si, zval ; TW
fstp qword ptr [si+8]
fstp qword ptr [si]

ret
invertz2 endp

END