| |
Conrad
Registered: Nov 2006 Posts: 849 |
How easy is it to calculate sine tables from the bare bones in ML?
Hi!
I'd like to have a go at coding my own routine of calculating sine/cosine tables without use of the BASIC interpreters (pi, sin(), etc) and just use pure ML instead.
Can I ask, how easy (or how SMALL) is this to do? Do I need to do additional algorithms like factorial or are there KERNAL routines for that (if any)? Multiplication code is no problem as I've seen articles on those, I'm just thinking about the rest of math involved with sine calculation.
Thanx in advance. |
|
... 22 posts hidden. Click here to view all posts.... |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quote: Anyone have an example on how to access the BASIC routines from asm to generate a sine? Also how compact is such a routine, are we talking like 50 bytes or 500 bytes?
Here's the best I could come up with on short notice (31 bytes):table = $0400 ;; preferably a low page
loop lda #<index
ldy #>index
jsr $bba2
jsr $e277
lda $61
adc #7
sta $61
jsr $bc9b
lda $65
index .byte $90
.byte $00
sta table
inc *-2
bne loop I suspect that the float-to-int portion could be shortened by making use of some sneaky ROM function somewhere. Interesting challenge though, anyone got a shorter implementation? |
| |
Frantic
Registered: Mar 2003 Posts: 1648 |
@Doynax: Would it be OK to post that on Codebase? |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quote: @Doynax: Would it be OK to post that on Codebase?
Look.. It's a code snippet posted on a public forum, of course you can use it. Feel free to modify it, sell it, claim you wrote it yourself or print it out and use it as toilet paper.
There are few things as obnoxious as tutorial authors and the like thinking they've got some sort of claim to your program when you based your code on their work..
By the way personally I'd like to see a decent tutorial on the BASIC floating point library in the code base. This is a good beginning but it's incomplete and full of errors. For instance I'd like to know why taking sin(0) seems to crash the program. |
| |
Frantic
Registered: Mar 2003 Posts: 1648 |
okok, I posted it and wrote that it was created by some lamer named Doynax (just kidding). |
| |
Shadow Account closed
Registered: Apr 2002 Posts: 355 |
Nice explanation that accompanied the codebase64 post, much appreciated! |
| |
Frantic
Registered: Mar 2003 Posts: 1648 |
Credits for those goes to (some lamer called) Doynax. ;) |
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
I managed to reduce the bloody thing by two bytes (to 29) by converting to integer through adding a 'magic' float. Well, it's actually a piece of code in the BASIC ROM but it works well enough as a float..
table = $0400 ;; Preferably a low page. Must be paged aligned!
loop lda #<index ;; Load 5-byte float at 'index' into FAC, the fraction
ldy #>index ;; of which is stepped between 0/256..255/256.
jsr $bba2 ;; However an integer bias is also added in order to fix
;; the exponent and make hence it possible to increment the
;; fraction as a normal binary byte, e.g. a version of the
;; classic x86 float-to-int conversion trick.
jsr $e277 ;; Now calculate sine of FAC. Except skip the initial part
;; of the BASIC function which divides by 2*PI to get
;; a fraction out of radians since we've already got one.
;; The integer bias is taken care by BASIC since sin()
;; is supposed to be periodic.
lda #<bias ;; Convert the output in FAC from a float in -1..+1 to a
ldy #>bias ;; fixed-point value in -128..+127 at the LSB of the
jsr $b867 ;; mantissa by employing the same trick as before of
lda $65 ;; adding a high integer bias.
index .byte $90 ;; This is both a float *and* a piece of code. The exponent
.byte $00 ;; ($90 corresponds to 2^16) fixes our 8-bit fraction as the
sta table ;; third byte of the mantissa and STA address' LSB (don't
;; forget that BASIC floats are big-endian!). And $90/$00
;; interpreted as code simply correspond to a harmless BCC *+2.
;; Note that while the STA's opcode is an integer part which
;; shouldn't affect the result, the table's high byte *does*
;; serve as a small offset shifting the result by up to one
;; index value. Some might even argue that placing the table
;; at $8000 would produce the 'proper' rounding.
inc *-2
bne loop
bias = $befa ;; A float with an exponent of $99 (2^25) and an LSB of
;; .byte $99 ;; zero is used to convert the output to binary. Such byte
;; .byte $02 ;; sequences can be found in six places in the BASIC/Kernal
;; .byte $01 ;; ROMs, at $befa/$bf04/$bf09/$fd53/$fd56/$ff38.
;; .byte $a9 ;; A version with an LSB of $80 would have been useful to
;; .byte $00 ;; create unsigned output (e.g. between $00 and $ff with the
;; origin at $80) but unfortunately doesn't seem to exist. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Nice, much smaller than my faked routine. But how fast is it compared to Basic?
|
| |
doynax Account closed
Registered: Oct 2004 Posts: 212 |
Quote: Nice, much smaller than my faked routine. But how fast is it compared to Basic?
The assembler version takes 5.89 seconds ($584f0f cycles) while a BASIC implementation needs about 17.2 seconds according to my stopwatch.
Then again BASIC isn't exactly my forte, so perhaps I made some stupid newbie mistake?0 fori=0to255:poke1024+i,sin(i*.02454)*128and255:next |
| |
Skate
Registered: Jul 2003 Posts: 494 |
I usually use something like;
0 FORI=0TO255:POKE1024+I,128+128*SIN(I/40.7):NEXT
where 40.7 is 256/(2*PI)
don't forget, we need less bytes for small intros and /40.7 is shorter ;) |
Previous - 1 | 2 | 3 | 4 - Next |