Article View: comp.sys.amiga.tech
Article #7621Re: Speeding up fractals,(Also here's a 64bit 030 example)
From: John Schultz
Date: Fri, 21 Dec 1990 01:39
Date: Fri, 21 Dec 1990 01:39
193 lines
6229 bytes
6229 bytes
In <86849@tut.cis.ohio-state.edu> berenfie@tortoise.cis.ohio-state.edu (gregory neil berenfield) writes:
[stuff deleted]
>plane and use z->z^2+c calculations accordingly. The mandelbrot is drawn
>fairly quickly but not nearly as fast as MandFXP and I want to squeeze
>maximum speed out of this sucker. Does anyone know of a way of storing
>floating points as ints and doing some sort of bit shifting stuff to do
>fp arithmatic operations? Any help in optimizing this thing would be
>of great help. Thanks.
First, MandFXP may be doing other tricks other than using a different
numeric format. These tricks are probably _mathematical_ in nature,
from knowledge known about the mandelbrot set. I doubt they are computing
the thing using brute force: they are probably using clever heuristics...
Anyway, it's easy to do fixed point arithmetic. Just pick a bit location
for your fixed point, say bit 14. Now after you multiply two 14 bit numbers,
you now have a 28 bit number. To get back to a 14 bit number, you shift
right by 14. Before you divide one 14 bit number by another, you must make
it a 28 bit number. Examples:
#define FBITS 14 /* Fixed point bits, 16384 == 1.0 */
long a,b,c; /* 14 bit numbers */
c = (a*b) >> FBITS;
c = (a << FBITS) / b;
c = (a*b)/c;
See the pattern? The rules are: Multiplication of two fixed point numbers
yields a fixed point number equal to the sum of the two number's fixed points.
Division yields the difference of the fixed points. The fixed point location
is called the RADIX. Using this terminology:
a*b yields a fixed point number with radix(a) + radix(b);
a/b " " radix(a) - radix(b);
You can mix radix' too:
radix(a) == 7, radix(b) = 14:
radix(a*b) = 21, radix((a*b)>>12) = 9, etc. Left shifts increase the radix,
right shifts decrease the radix.
IMPORTANT: You *must* make sure that the radix is the same for both numbers
when adding or subtracting. You _can_ do things like:
x = (a*a + b*b + c*c) >> FBITS; /* a,b,c and x have the same radix */
Also, sqrt *halves* the radix, just as squaring a number doubles the radix.
Now, if you use the 68030, you should use 64 bit numbers (at least for
intermediate values). Use the addx.l, muls.l, divs.l, bfextu, and bfins
to manipulate your numbers. Here's a short example:
; rotate64, created by John Schultz
; Rotates a point in 3D space.
; Created 8-Aug-90
section math64,code
OPT p=68020/68881 ; for Adapt assembler
xdef _rotate64
FB equ 14 ; fixed point precision (bits 0-14)
RB equ (32-FB) ; remaining bits (32-14 = 18)
; 32 bit rotation matrix offsets
ma equ 0
mb equ 4
mc equ 8
md equ 12
me equ 16
mf equ 20
mg equ 24
mh equ 28
mi equ 32
; 32 bit 3D point offsets
px equ 0
py equ 4
pz equ 8
;void longrotate(matrix * m,longpoint3d * p,ushort fbits) {
;long tcx,tcy,tcz;
; tcx = p->x;
; tcy = p->y;
; tcz = p->z;
; p->x = (m->a1*tcx + m->d1*tcy + m->g1*tcz) >> fbits;
; p->y = (m->b1*tcx + m->e1*tcy + m->h1*tcz) >> fbits;
; p->z = (m->c1*tcx + m->f1*tcy + m->i1*tcz) >> fbits;
;} /* longrotate */
; extern __asm rotate64(register __a0 matrix * m,
; register __a1 longpoint3d * p);
; a0 = matrix *, a1 = longpoint3d *
_rotate64:
movem.l d2-d6,-(sp)
movem.l (a1),d0-d2 ; x,y,z
; Rotate X
move.l (a0),d4 ; ma
muls.l d0,d3:d4 ; x*a, 64 bit result in d3:d4
move.l md(a0),d6 ; md
muls.l d1,d5:d6 ; y*d, 64 bit result in d5:d6
add.l d4,d6 ; low 32 bits, x*a + y*d
addx.l d3,d5 ; high 32 bits, x*a + y*d (d6:d5 = res)
move.l mg(a0),d4 ; mg
muls.l d2,d3:d4 ; z*g, 64 bit result in d3:d4
add.l d4,d6 ; low 32 bits, x*a + y*d + z*g
addx.l d3,d5 ; high 32 bits, x*a + y*d + z*g (d5:d6 = res)
; Result is in (high:low) d5:d6
bfextu d6{0:RB},d6 ; shift right by 32-RB
bfins d5,d6{0:FB} ; insert bits from high word
move.l d6,(a1)+ ; save rotated x
; Rotate Y
move.l mb(a0),d4 ; ma
muls.l d0,d3:d4 ; x*b, 64 bit result in d3:d4
move.l me(a0),d6 ; md
muls.l d1,d5:d6 ; y*e, 64 bit result in d5:d6
add.l d4,d6 ; low 32 bits, x*b + y*e
addx.l d3,d5 ; high 32 bits, x*b + y*e (d5:d6 = res)
move.l mh(a0),d4 ; mg
muls.l d2,d3:d4 ; z*g, 64 bit result in d3:d4
add.l d4,d6 ; low 32 bits, x*b + y*e + z*h
addx.l d3,d5 ; high 32 bits, x*b + y*e + z*h (d5:d6 = res)
; Result is in (high:low) d5:d6
bfextu d6{0:RB},d6 ; shift right by 32-RB
bfins d5,d6{0:FB} ; insert bits from high word
move.l d6,(a1)+ ; save rotated y
; Rotate Z
move.l mc(a0),d4 ; mc
muls.l d0,d3:d4 ; x*c, 64 bit result in d3:d4
move.l mf(a0),d6 ; md
muls.l d1,d5:d6 ; y*f, 64 bit result in d5:d6
add.l d4,d6 ; low 32 bits, x*c + y*f
addx.l d3,d5 ; high 32 bits, x*c + y*f (d6:d5 = res)
move.l mi(a0),d4 ; mg
muls.l d2,d3:d4 ; z*g, 64 bit result in d3:d4
add.l d4,d6 ; low 32 bits, x*c + y*f + z*i
addx.l d3,d5 ; high 32 bits, x*c + y*f + z*i (d5:d6 = res)
; Result is in (high:low) d5:d6
bfextu d6{0:RB},d6 ; shift right by 32-FB
bfins d5,d6{0:FB} ; insert bits from high word
move.l d6,(a1) ; save rotated z
movem.l (sp)+,d2-d6
rts
END
One last thing, if you are constantly using the fsqrt of the 882,
the fmove.l instruction is 100 cycles, so you may not see a big win
using integer in some cases. Multiplies and divides aren't much slower
on the 882 (than muls.l/divs.l), especially if you use fsglmul/div, but
adds and subtracts are slower than multiplies and divides! This makes
sense as the processor must align the bits (floating) before performing
adds or subs. Hope this helps,
John
Technical Details
Message-ID:
<6441@crash.cts.com>Path:
arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!usc!jarthur!ucivax!orion.oac.uci.edu!ucsd!nosc!crash!jcsReferences:
<86849@tut.cis.ohio-state.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!usc!jarthur!ucivax!orion.oac.uci.edu!ucsd!nosc!crash!jcs From: jcs@crash.cts.com (John Schultz) Newsgroups: comp.sys.amiga.tech Subject: Re: Speeding up fractals,(Also here's a 64bit 030 example) Message-ID: <6441@crash.cts.com> Date: 21 Dec 90 01:39:09 GMT References: <86849@tut.cis.ohio-state.edu> Distribution: comp.sys.amiga.tech Organization: Crash TimeSharing, El Cajon, CA Lines: 193