add cosr8, sinr8, cosr16 and sinr16 builtin functions that take a degree 0..179 (= 0..358 in 2 degree steps)

to more easily scale halves/quarters etc of a circle than possible with the ones that take 0..255 'degrees'.
This commit is contained in:
Irmen de Jong 2021-11-09 23:36:47 +01:00
parent 84dafda0e4
commit 8df3da11e3
8 changed files with 373 additions and 7 deletions

View File

@ -46,7 +46,9 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
"sum" -> funcSum(fcall, resultToStack, resultRegister, sscope) "sum" -> funcSum(fcall, resultToStack, resultRegister, sscope)
"any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope) "any", "all" -> funcAnyAll(fcall, func, resultToStack, resultRegister, sscope)
"sin8", "sin8u", "sin16", "sin16u", "sin8", "sin8u", "sin16", "sin16u",
"cos8", "cos8u", "cos16", "cos16u" -> funcSinCosInt(fcall, func, resultToStack, resultRegister, sscope) "sinr8", "sinr8u", "sinr16", "sinr16u",
"cos8", "cos8u", "cos16", "cos16u",
"cosr8", "cosr8u", "cosr16", "cosr16u" -> funcSinCosInt(fcall, func, resultToStack, resultRegister, sscope)
"sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope) "sgn" -> funcSgn(fcall, func, resultToStack, resultRegister, sscope)
"sin", "cos", "tan", "atan", "sin", "cos", "tan", "atan",
"ln", "log2", "sqrt", "rad", "ln", "log2", "sqrt", "rad",
@ -283,11 +285,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
asmgen.out(" jsr prog8_lib.func_${func.name}_stack") asmgen.out(" jsr prog8_lib.func_${func.name}_stack")
else else
when(func.name) { when(func.name) {
"sin8", "sin8u", "cos8", "cos8u" -> { "sin8", "sin8u", "sinr8", "sinr8u", "cos8", "cos8u", "cosr8", "cosr8u" -> {
asmgen.out(" jsr prog8_lib.func_${func.name}_into_A") asmgen.out(" jsr prog8_lib.func_${func.name}_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, scope, program, asmgen), CpuRegister.A) assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, scope, program, asmgen), CpuRegister.A)
} }
"sin16", "sin16u", "cos16", "cos16u" -> { "sin16", "sin16u", "sinr16", "sinr16u", "cos16", "cos16u", "cosr16", "cosr16u" -> {
asmgen.out(" jsr prog8_lib.func_${func.name}_into_AY") asmgen.out(" jsr prog8_lib.func_${func.name}_into_AY")
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, scope, program, asmgen), RegisterOrPair.AY) assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, scope, program, asmgen), RegisterOrPair.AY)
} }

View File

@ -91,6 +91,13 @@ func_sin8_into_A .proc
_sinecos8 .char trunc(127.0 * sin(range(256+64) * rad(360.0/256.0))) _sinecos8 .char trunc(127.0 * sin(range(256+64) * rad(360.0/256.0)))
.pend .pend
func_sinr8_into_A .proc
tay
lda _sinecosR8,y
rts
_sinecosR8 .char trunc(127.0 * sin(range(180+45) * rad(360.0/180.0)))
.pend
func_sin8u_into_A .proc func_sin8u_into_A .proc
tay tay
lda _sinecos8u,y lda _sinecos8u,y
@ -98,6 +105,13 @@ func_sin8u_into_A .proc
_sinecos8u .byte trunc(128.0 + 127.5 * sin(range(256+64) * rad(360.0/256.0))) _sinecos8u .byte trunc(128.0 + 127.5 * sin(range(256+64) * rad(360.0/256.0)))
.pend .pend
func_sinr8u_into_A .proc
tay
lda _sinecosR8u,y
rts
_sinecosR8u .byte trunc(128.0 + 127.5 * sin(range(180+45) * rad(360.0/180.0)))
.pend
func_sin8_stack .proc func_sin8_stack .proc
tay tay
lda func_sin8_into_A._sinecos8,y lda func_sin8_into_A._sinecos8,y
@ -106,6 +120,14 @@ func_sin8_stack .proc
rts rts
.pend .pend
func_sinr8_stack .proc
tay
lda func_sinr8_into_A._sinecosR8,y
sta P8ESTACK_LO,x
dex
rts
.pend
func_sin8u_stack .proc func_sin8u_stack .proc
tay tay
lda func_sin8u_into_A._sinecos8u,y lda func_sin8u_into_A._sinecos8u,y
@ -114,18 +136,38 @@ func_sin8u_stack .proc
rts rts
.pend .pend
func_sinr8u_stack .proc
tay
lda func_sinr8u_into_A._sinecosR8u,y
sta P8ESTACK_LO,x
dex
rts
.pend
func_cos8_into_A .proc func_cos8_into_A .proc
tay tay
lda func_sin8_into_A._sinecos8+64,y lda func_sin8_into_A._sinecos8+64,y
rts rts
.pend .pend
func_cosr8_into_A .proc
tay
lda func_sinr8_into_A._sinecosR8+45,y
rts
.pend
func_cos8u_into_A .proc func_cos8u_into_A .proc
tay tay
lda func_sin8u_into_A._sinecos8u+64,y lda func_sin8u_into_A._sinecos8u+64,y
rts rts
.pend .pend
func_cosr8u_into_A .proc
tay
lda func_sinr8u_into_A._sinecosR8u+45,y
rts
.pend
func_cos8_stack .proc func_cos8_stack .proc
tay tay
lda func_sin8_into_A._sinecos8+64,y lda func_sin8_into_A._sinecos8+64,y
@ -134,6 +176,14 @@ func_cos8_stack .proc
rts rts
.pend .pend
func_cosr8_stack .proc
tay
lda func_sinr8_into_A._sinecosR8+45,y
sta P8ESTACK_LO,x
dex
rts
.pend
func_cos8u_stack .proc func_cos8u_stack .proc
tay tay
lda func_sin8u_into_A._sinecos8u+64,y lda func_sin8u_into_A._sinecos8u+64,y
@ -142,6 +192,14 @@ func_cos8u_stack .proc
rts rts
.pend .pend
func_cosr8u_stack .proc
tay
lda func_sinr8u_into_A._sinecosR8u+45,y
sta P8ESTACK_LO,x
dex
rts
.pend
func_sin16_into_AY .proc func_sin16_into_AY .proc
tay tay
lda _sinecos8lo,y lda _sinecos8lo,y
@ -155,6 +213,19 @@ _sinecos8lo .byte <_
_sinecos8hi .byte >_ _sinecos8hi .byte >_
.pend .pend
func_sinr16_into_AY .proc
tay
lda _sinecosR8lo,y
pha
lda _sinecosR8hi,y
tay
pla
rts
_ := trunc(32767.0 * sin(range(180+45) * rad(360.0/180.0)))
_sinecosR8lo .byte <_
_sinecosR8hi .byte >_
.pend
func_sin16u_into_AY .proc func_sin16u_into_AY .proc
tay tay
lda _sinecos8ulo,y lda _sinecos8ulo,y
@ -168,6 +239,18 @@ _sinecos8ulo .byte <_
_sinecos8uhi .byte >_ _sinecos8uhi .byte >_
.pend .pend
func_sinr16u_into_AY .proc
tay
lda _sinecosR8ulo,y
pha
lda _sinecosR8uhi,y
tay
pla
rts
_ := trunc(32768.0 + 32767.5 * sin(range(180+45) * rad(360.0/180.0)))
_sinecosR8ulo .byte <_
_sinecosR8uhi .byte >_
.pend
func_sin16_stack .proc func_sin16_stack .proc
tay tay
@ -179,6 +262,16 @@ func_sin16_stack .proc
rts rts
.pend .pend
func_sinr16_stack .proc
tay
lda func_sinr16_into_AY._sinecosR8lo,y
sta P8ESTACK_LO,x
lda func_sinr16_into_AY._sinecosR8hi,y
sta P8ESTACK_HI,x
dex
rts
.pend
func_sin16u_stack .proc func_sin16u_stack .proc
tay tay
lda func_sin16u_into_AY._sinecos8ulo,y lda func_sin16u_into_AY._sinecos8ulo,y
@ -189,6 +282,16 @@ func_sin16u_stack .proc
rts rts
.pend .pend
func_sinr16u_stack .proc
tay
lda func_sinr16u_into_AY._sinecosR8ulo,y
sta P8ESTACK_LO,x
lda func_sinr16u_into_AY._sinecosR8uhi,y
sta P8ESTACK_HI,x
dex
rts
.pend
func_cos16_into_AY .proc func_cos16_into_AY .proc
tay tay
lda func_sin16_into_AY._sinecos8lo+64,y lda func_sin16_into_AY._sinecos8lo+64,y
@ -199,6 +302,16 @@ func_cos16_into_AY .proc
rts rts
.pend .pend
func_cosr16_into_AY .proc
tay
lda func_sinr16_into_AY._sinecosR8lo+45,y
pha
lda func_sinr16_into_AY._sinecosR8hi+45,y
tay
pla
rts
.pend
func_cos16u_into_AY .proc func_cos16u_into_AY .proc
tay tay
lda func_sin16u_into_AY._sinecos8ulo+64,y lda func_sin16u_into_AY._sinecos8ulo+64,y
@ -209,6 +322,16 @@ func_cos16u_into_AY .proc
rts rts
.pend .pend
func_cosr16u_into_AY .proc
tay
lda func_sinr16u_into_AY._sinecosR8ulo+45,y
pha
lda func_sinr16u_into_AY._sinecosR8uhi+45,y
tay
pla
rts
.pend
func_cos16_stack .proc func_cos16_stack .proc
tay tay
lda func_sin16_into_AY._sinecos8lo+64,y lda func_sin16_into_AY._sinecos8lo+64,y
@ -219,6 +342,16 @@ func_cos16_stack .proc
rts rts
.pend .pend
func_cosr16_stack .proc
tay
lda func_sinr16_into_AY._sinecosR8lo+45,y
sta P8ESTACK_LO,x
lda func_sinr16_into_AY._sinecosR8hi+45,y
sta P8ESTACK_HI,x
dex
rts
.pend
func_cos16u_stack .proc func_cos16u_stack .proc
tay tay
lda func_sin16u_into_AY._sinecos8ulo+64,y lda func_sin16u_into_AY._sinecos8ulo+64,y
@ -229,6 +362,16 @@ func_cos16u_stack .proc
rts rts
.pend .pend
func_cosr16u_stack .proc
tay
lda func_sinr16u_into_AY._sinecosR8ulo+45,y
sta P8ESTACK_LO,x
lda func_sinr16u_into_AY._sinecosR8uhi+45,y
sta P8ESTACK_HI,x
dex
rts
.pend
abs_b_stack .proc abs_b_stack .proc
; -- push abs(A) on stack (as byte) ; -- push abs(A) on stack (as byte)
jsr abs_b_into_A jsr abs_b_into_A

View File

@ -429,7 +429,7 @@ internal class AstChecker(private val program: Program,
if(targetDt.isIterable) if(targetDt.isIterable)
errors.err("cannot assign value to string or array", assignment.value.position) errors.err("cannot assign value to string or array", assignment.value.position)
else if(!(valueDt istype DataType.STR && targetDt istype DataType.UWORD)) else if(!(valueDt istype DataType.STR && targetDt istype DataType.UWORD))
errors.err("type of value doesn't match target", assignment.value.position) errors.err("type of value $valueDt doesn't match target $targetDt", assignment.value.position)
} }
if(assignment.value is TypecastExpression) { if(assignment.value is TypecastExpression) {

View File

@ -87,6 +87,9 @@ class TestCompilerOnExamplesCx16: FunSpec({
"kefrenbars", "kefrenbars",
"mandelbrot-gfx-colors", "mandelbrot-gfx-colors",
"multipalette", "multipalette",
"rasterbars",
"sincos",
"tehtriz",
"testgfx2", "testgfx2",
), ),
listOf(false, true) listOf(false, true)

View File

@ -109,11 +109,19 @@ private val functionSignatures: List<FSignature> = listOf(
FSignature("sin8u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UBYTE, ::builtinSin8u ), FSignature("sin8u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UBYTE, ::builtinSin8u ),
FSignature("sin16" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.WORD, ::builtinSin16 ), FSignature("sin16" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.WORD, ::builtinSin16 ),
FSignature("sin16u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UWORD, ::builtinSin16u ), FSignature("sin16u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UWORD, ::builtinSin16u ),
FSignature("sinr8" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.BYTE, ::builtinSinR8 ),
FSignature("sinr8u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UBYTE, ::builtinSinR8u ),
FSignature("sinr16" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.WORD, ::builtinSinR16 ),
FSignature("sinr16u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UWORD, ::builtinSinR16u ),
FSignature("cos" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::cos) }, FSignature("cos" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::cos) },
FSignature("cos8" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.BYTE, ::builtinCos8 ), FSignature("cos8" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.BYTE, ::builtinCos8 ),
FSignature("cos8u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UBYTE, ::builtinCos8u ), FSignature("cos8u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UBYTE, ::builtinCos8u ),
FSignature("cos16" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.WORD, ::builtinCos16 ), FSignature("cos16" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.WORD, ::builtinCos16 ),
FSignature("cos16u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UWORD, ::builtinCos16u ), FSignature("cos16u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UWORD, ::builtinCos16u ),
FSignature("cosr8" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.BYTE, ::builtinCosR8 ),
FSignature("cosr8u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UBYTE, ::builtinCosR8u ),
FSignature("cosr16" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.WORD, ::builtinCosR16 ),
FSignature("cosr16u" , true, listOf(FParam("angle8", arrayOf(DataType.UBYTE))), DataType.UWORD, ::builtinCosR16u ),
FSignature("tan" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::tan) }, FSignature("tan" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::tan) },
FSignature("atan" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::atan) }, FSignature("atan" , true, listOf(FParam("rads", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::atan) },
FSignature("ln" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::log) }, FSignature("ln" , true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::log) },
@ -372,6 +380,24 @@ private fun builtinSin8u(args: List<Expression>, position: Position, program: Pr
return NumericLiteralValue(DataType.UBYTE, (128.0 + 127.5 * sin(rad)).toInt().toShort(), position) return NumericLiteralValue(DataType.UBYTE, (128.0 + 127.5 * sin(rad)).toInt().toShort(), position)
} }
@Suppress("UNUSED_PARAMETER")
private fun builtinSinR8(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("sinr8 requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.BYTE, (127.0 * sin(rad)).toInt().toShort(), position)
}
@Suppress("UNUSED_PARAMETER")
private fun builtinSinR8u(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("sinr8u requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.UBYTE, (128.0 + 127.5 * sin(rad)).toInt().toShort(), position)
}
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
private fun builtinCos8(args: List<Expression>, position: Position, program: Program): NumericLiteralValue { private fun builtinCos8(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1) if (args.size != 1)
@ -390,6 +416,24 @@ private fun builtinCos8u(args: List<Expression>, position: Position, program: Pr
return NumericLiteralValue(DataType.UBYTE, (128.0 + 127.5 * cos(rad)).toInt().toShort(), position) return NumericLiteralValue(DataType.UBYTE, (128.0 + 127.5 * cos(rad)).toInt().toShort(), position)
} }
@Suppress("UNUSED_PARAMETER")
private fun builtinCosR8(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("cosr8 requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.BYTE, (127.0 * cos(rad)).toInt().toShort(), position)
}
@Suppress("UNUSED_PARAMETER")
private fun builtinCosR8u(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("cosr8u requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.UBYTE, (128.0 + 127.5 * cos(rad)).toInt().toShort(), position)
}
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
private fun builtinSin16(args: List<Expression>, position: Position, program: Program): NumericLiteralValue { private fun builtinSin16(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1) if (args.size != 1)
@ -408,6 +452,24 @@ private fun builtinSin16u(args: List<Expression>, position: Position, program: P
return NumericLiteralValue(DataType.UWORD, (32768.0 + 32767.5 * sin(rad)).toInt(), position) return NumericLiteralValue(DataType.UWORD, (32768.0 + 32767.5 * sin(rad)).toInt(), position)
} }
@Suppress("UNUSED_PARAMETER")
private fun builtinSinR16(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("sinr16 requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.WORD, (32767.0 * sin(rad)).toInt(), position)
}
@Suppress("UNUSED_PARAMETER")
private fun builtinSinR16u(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("sinr16u requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.UWORD, (32768.0 + 32767.5 * sin(rad)).toInt(), position)
}
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
private fun builtinCos16(args: List<Expression>, position: Position, program: Program): NumericLiteralValue { private fun builtinCos16(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1) if (args.size != 1)
@ -426,6 +488,24 @@ private fun builtinCos16u(args: List<Expression>, position: Position, program: P
return NumericLiteralValue(DataType.UWORD, (32768.0 + 32767.5 * cos(rad)).toInt(), position) return NumericLiteralValue(DataType.UWORD, (32768.0 + 32767.5 * cos(rad)).toInt(), position)
} }
@Suppress("UNUSED_PARAMETER")
private fun builtinCosR16(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("cosr16 requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.WORD, (32767.0 * cos(rad)).toInt(), position)
}
@Suppress("UNUSED_PARAMETER")
private fun builtinCosR16u(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1)
throw SyntaxError("cosr16u requires one argument", position)
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
val rad = constval.number.toDouble() / 180.0 * 2.0 * PI
return NumericLiteralValue(DataType.UWORD, (32768.0 + 32767.5 * cos(rad)).toInt(), position)
}
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
private fun builtinSgn(args: List<Expression>, position: Position, program: Program): NumericLiteralValue { private fun builtinSgn(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
if (args.size != 1) if (args.size != 1)

View File

@ -704,6 +704,22 @@ cos16u(x)
cos16(x) cos16(x)
Fast 16-bit word cosine of angle 0..255, result is in range -32767..32767 Fast 16-bit word cosine of angle 0..255, result is in range -32767..32767
cosr8u(x)
Fast 8-bit ubyte cosine of angle 0..179 (each is a 2 degree step), result is in range 0..255
Angles 180..255 will yield a garbage result!
cosr8(x)
Fast 8-bit byte cosine of angle 0..179 (each is a 2 degree step), result is in range -127..127
Angles 180..255 will yield a garbage result!
cosr16u(x)
Fast 16-bit uword cosine of angle 0..179 (each is a 2 degree step), result is in range 0..65535
Angles 180..255 will yield a garbage result!
cosr16(x)
Fast 16-bit word cosine of angle 0..179 (each is a 2 degree step), result is in range -32767..32767
Angles 180..255 will yield a garbage result!
deg(x) deg(x)
Radians to degrees. Radians to degrees.
@ -740,6 +756,22 @@ sin16u(x)
sin16(x) sin16(x)
Fast 16-bit word sine of angle 0..255, result is in range -32767..32767 Fast 16-bit word sine of angle 0..255, result is in range -32767..32767
sinr8u(x)
Fast 8-bit ubyte sine of angle 0..179 (each is a 2 degree step), result is in range 0..255
Angles 180..255 will yield a garbage result!
sinr8(x)
Fast 8-bit byte sine of angle 0..179 (each is a 2 degree step), result is in range -127..127
Angles 180..255 will yield a garbage result!
sinr16u(x)
Fast 16-bit uword sine of angle 0..179 (each is a 2 degree step), result is in range 0..65535
Angles 180..255 will yield a garbage result!
sinr16(x)
Fast 16-bit word sine of angle 0..179 (each is a 2 degree step), result is in range -32767..32767
Angles 180..255 will yield a garbage result!
sqrt16(w) sqrt16(w)
16 bit unsigned integer Square root. Result is unsigned byte. 16 bit unsigned integer Square root. Result is unsigned byte.
To do the reverse, squaring an integer, just write ``x*x``. To do the reverse, squaring an integer, just write ``x*x``.

View File

@ -3,9 +3,6 @@ TODO
For next compiler release (7.3) For next compiler release (7.3)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- add cosr8, sinr8, cosr16 and sinr16 that take a degree 0..179 (= 0..359 in 2 degree steps)
to more easily scale halves/quarters etc of a circle than possible with the ones that take 0..255 'degrees'.
- if-statement expression simplification sometimes increases code size (Petaxian) FIX THIS! - if-statement expression simplification sometimes increases code size (Petaxian) FIX THIS!
- add expression simplification to while and until loops as well. - add expression simplification to while and until loops as well.
- let typecasting code use expression.typecastTo() - let typecasting code use expression.typecastTo()

109
examples/cx16/sincos.p8 Normal file
View File

@ -0,0 +1,109 @@
%import graphics
; Note: this program is compatible with CX16 only.
; it doesn't work correctly on C64 because the bitmap screen data overlaps
; the program itself in memory $2000-...
main {
const uword width = 320
const ubyte height = 200
sub start() {
graphics.enable_bitmap_mode()
sincos255()
sys.wait(120)
graphics.clear_screen(1, 0)
sincos180()
sys.wait(120)
graphics.clear_screen(1, 0)
circles()
repeat {
}
}
sub sincos255() {
graphics.line(256,0,256,height-1)
ubyte pixelyb
uword pixelyw
ubyte pixelxb
for pixelxb in 0 to 255 {
pixelyb = cos8u(pixelxb) / 2
graphics.plot(pixelxb, pixelyb)
pixelyb = sin8u(pixelxb) / 2
graphics.plot(pixelxb, pixelyb)
}
for pixelxb in 0 to 255 {
pixelyw = cos16u(pixelxb) / 1024 + 120
graphics.plot(pixelxb, lsb(pixelyw))
pixelyw = sin16u(pixelxb) / 1024 + 120
graphics.plot(pixelxb, lsb(pixelyw))
}
}
sub sincos180() {
graphics.line(180,0,180,height-1)
ubyte pixelyb
uword pixelyw
ubyte pixelxb
for pixelxb in 0 to 179 {
pixelyb = cosr8u(pixelxb) / 2
graphics.plot(pixelxb, pixelyb)
pixelyb = sinr8u(pixelxb) / 2
graphics.plot(pixelxb, pixelyb)
}
for pixelxb in 0 to 179 {
pixelyw = cosr16u(pixelxb) / 1024 + 120
graphics.plot(pixelxb, lsb(pixelyw))
pixelyw = sinr16u(pixelxb) / 1024 + 120
graphics.plot(pixelxb, lsb(pixelyw))
}
}
sub circles() {
ubyte pixelyb
uword pixelxw
ubyte r
; circles with "degrees" from 0 to 255
; TODO FIX WHEN USING NO-OPT! (CORRECT WHEN USING OPTIMIZATION..)
for r in 0 to 255 {
pixelxw = (sin8(r)/2 + 80) as uword
pixelyb = (cos8(r)/2 + height/2) as ubyte
graphics.plot(pixelxw, pixelyb)
}
for r in 0 to 255 {
pixelxw = (sin16(r)/1024 + 80) as uword
pixelyb = (cos16(r)/1024 + height/2) as ubyte
graphics.plot(pixelxw, pixelyb)
}
; circles with half-degrees from 0 to 179 (=full degrees 0..358 with steps of 2 degrees)
; TODO FIX WHEN USING NO-OPT! (CORRECT WHEN USING OPTIMIZATION..)
for r in 0 to 179 {
pixelxw = (sinr8(r) as word /2 + 220) as uword
pixelyb = (cosr8(r)/2 + height/2) as ubyte
graphics.plot(pixelxw, pixelyb)
}
for r in 0 to 179 {
pixelxw = (sinr16(r) as word /1024 + 220) as uword
pixelyb = (cosr16(r)/1024 + height/2) as ubyte
graphics.plot(pixelxw, pixelyb)
}
}
}