Last active
February 4, 2022 13:45
-
-
Save Zeda/98aab98fd32a231b878772a435ffb306 to your computer and use it in GitHub Desktop.
8-bit Sine Approximation using bit twiddling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# This is ported from: | |
# https://www.omnimaga.org/asm-language/sine-approximation-(z80)/ | |
# (Xeda112358 a.k.a. Zeda a.k.a. ZedaZ80) | |
# | |
from math import sin | |
def sineb(x): | |
"""Approximates 128*sin(x*2*pi/256)""" | |
a1 = int(x) | |
a0 = a1 << 1 | |
a2 = a1 >> 1 | |
# iteration 1 | |
if a1 & 64: | |
l = ~a0 & 127 | |
else: | |
l = a0 & 127 | |
# iteration 2 | |
if a1 & 32: | |
l += ~a1 & 31 # 30 will have better overall accuracy, but a more jagged curve | |
else: | |
l += a1 & 31 # 30 | |
# iteration 3 | |
if a1 & 16: | |
l += ~a2 & 7 # 6 will have better overall accuracy, but a more jagged curve | |
else: | |
l += a2 & 7 # 6 | |
# check if it needs to be negated | |
if a1 & 128: | |
return -l | |
else: | |
return l | |
# Plot a graph of the approximation vs the actual | |
for x in range(0, 256, 2): | |
y = sineb(x) | |
z = int(sin(x*3.1415926535/128)*128) | |
# translate and scale for "graphing" | |
y += 128 | |
z += 128 | |
y >>= 1 | |
z >>= 1 | |
# "graph" | |
# X - Approximation | |
# O - Actual | |
# 8 - used when the graphs overlap | |
if y == z: | |
print(" "*y + "8") | |
elif y > z: | |
print(" "*z + "O" + " "*(y-z-1) + "X") | |
else: | |
print(" "*y + "X" + " "*(z-y-1) + "O") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cosine: | |
; same inputs/outputs as sine | |
add a,64 ; cos(x) = sin(x + pi/2) | |
sine: | |
;Approximates 128*sin(A*2*pi/256) | |
;Input: | |
; A is the input, [0, 256) map to [0, 2pi) | |
;Output: | |
; A is the result | |
; C is a copy of the input | |
;Destroys: | |
; B, L | |
; | |
;Speed: 137cc or 149cc (if the input is >= 128) | |
;Size: 37 bytes | |
; | |
ld c,a ; a1 | |
add a,a | |
add a,a | |
ld b,a ; a2 | |
sbc a,a | |
xor b | |
rra | |
ld l,a | |
ld a,c | |
and 32 | |
add a,-32 | |
sbc a,a | |
xor c | |
and 31 ; Change to `30` for a jagged curve, but better average performance | |
add a,l | |
ld l,a | |
ld a,c | |
rra | |
ld b,a | |
and 8 | |
add a,-8 | |
sbc a,a | |
xor b | |
and 7 ; Change to `6` for a jagged curve, but better average performance | |
add a,l | |
bit 7,c | |
ret z | |
neg | |
ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment