mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
abs() now works on multiple data types including float.
no need to use floats.fabs() anymore
This commit is contained in:
parent
319079de7a
commit
38efe25c68
@ -79,7 +79,10 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
// cmp returns a status in the carry flag, but not a proper return value
|
||||
"cmp" to FSignature(false, listOf(FParam("value1", IntegerDatatypesNoBool), FParam("value2", NumericDatatypesNoBool)), null),
|
||||
"prog8_lib_stringcompare" to FSignature(true, listOf(FParam("str1", arrayOf(DataType.STR)), FParam("str2", arrayOf(DataType.STR))), DataType.BYTE),
|
||||
"abs" to FSignature(true, listOf(FParam("value", IntegerDatatypesNoBool)), DataType.UWORD),
|
||||
"abs" to FSignature(true, listOf(), null),
|
||||
"abs__byte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.BYTE))), DataType.BYTE),
|
||||
"abs__word" to FSignature(true, listOf(FParam("value", arrayOf(DataType.WORD))), DataType.WORD),
|
||||
"abs__float" to FSignature(true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT),
|
||||
"len" to FSignature(true, listOf(FParam("values", IterableDatatypes)), DataType.UWORD),
|
||||
// normal functions follow:
|
||||
"sizeof" to FSignature(true, listOf(FParam("object", DataType.values())), DataType.UBYTE),
|
||||
|
@ -33,7 +33,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
"mkword" -> funcMkword(fcall, resultToStack, resultRegister)
|
||||
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultToStack, resultRegister)
|
||||
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultToStack, resultRegister)
|
||||
"abs" -> funcAbs(fcall, resultToStack, resultRegister, sscope)
|
||||
"abs__byte", "abs__word", "abs__float" -> funcAbs(fcall, resultToStack, resultRegister, sscope)
|
||||
"any", "all" -> funcAnyAll(fcall, resultToStack, resultRegister, sscope)
|
||||
"sgn" -> funcSgn(fcall, resultToStack, resultRegister, sscope)
|
||||
"sqrt" -> funcSqrt(fcall, resultToStack, resultRegister, sscope)
|
||||
@ -301,6 +301,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun funcSqrt(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
|
||||
require(fcall.type != DataType.FLOAT)
|
||||
translateArguments(fcall, scope)
|
||||
if(resultToStack)
|
||||
asmgen.out(" jsr prog8_lib.func_sqrt16_stack")
|
||||
@ -679,21 +680,32 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val dt = fcall.args.single().type
|
||||
if(resultToStack) {
|
||||
when (dt) {
|
||||
DataType.UBYTE -> asmgen.out(" ldy #0")
|
||||
DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_stack")
|
||||
DataType.UWORD -> {}
|
||||
DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_stack")
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("no support for abs onto stack for this dt")
|
||||
}
|
||||
} else {
|
||||
when (dt) {
|
||||
DataType.UBYTE -> asmgen.out(" ldy #0")
|
||||
DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_into_AY")
|
||||
DataType.UWORD -> {}
|
||||
DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_into_AY")
|
||||
DataType.BYTE -> {
|
||||
asmgen.out(" jsr prog8_lib.abs_b_into_A")
|
||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A,false)
|
||||
}
|
||||
DataType.WORD -> {
|
||||
asmgen.out(" jsr prog8_lib.abs_w_into_AY")
|
||||
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
asmgen.out(" jsr floats.func_abs_f_into_FAC1")
|
||||
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
|
||||
}
|
||||
DataType.UBYTE -> {
|
||||
asmgen.assignRegister(RegisterOrPair.A, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.A, false, fcall.position, scope, asmgen))
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
asmgen.assignRegister(RegisterOrPair.AY, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.AY, false, fcall.position, scope, asmgen))
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
}
|
||||
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
return when(call.name) {
|
||||
"any" -> funcAny(call)
|
||||
"all" -> funcAll(call)
|
||||
"abs" -> funcAbs(call)
|
||||
"abs__byte", "abs__word", "abs__float" -> funcAbs(call)
|
||||
"cmp" -> funcCmp(call)
|
||||
"sgn" -> funcSgn(call)
|
||||
"sqrt" -> funcSqrt(call)
|
||||
@ -165,12 +165,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val tr = exprGen.translateExpression(call.args[0])
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
when (sourceDt) {
|
||||
DataType.UBYTE -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1 = tr.resultReg)
|
||||
}
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, tr.resultReg, -1)
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
val compareReg = codeGen.registers.nextFree()
|
||||
@ -196,7 +190,12 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
result += IRCodeChunk(notNegativeLabel, null)
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, tr.resultReg, -1)
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
DataType.FLOAT -> {
|
||||
val resultFpReg = codeGen.registers.nextFreeFloat()
|
||||
addInstr(result, IRInstruction(Opcode.FABS, IRDataType.FLOAT, fpReg1 = resultFpReg, fpReg2 = tr.resultFpReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.FLOAT, -1, resultFpReg)
|
||||
}
|
||||
else -> throw AssemblyError("weird dt")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,27 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err
|
||||
functionCallExpr))
|
||||
}
|
||||
}
|
||||
else if(func==listOf("abs")) {
|
||||
val t1 = functionCallExpr.args[0].inferType(program)
|
||||
if(t1.isKnown) {
|
||||
val dt = t1.getOrElse { throw InternalCompilerException("invalid dt") }
|
||||
val replaceFunc = when(dt) {
|
||||
DataType.BYTE -> "abs__byte"
|
||||
DataType.WORD -> "abs__word"
|
||||
DataType.FLOAT -> "abs__float"
|
||||
DataType.UBYTE, DataType.UWORD -> {
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr, functionCallExpr.args[0], parent))
|
||||
}
|
||||
else -> {
|
||||
errors.err("expected numeric argument", functionCallExpr.position)
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
return listOf(IAstModification.SetExpression({functionCallExpr.target = it as IdentifierReference},
|
||||
IdentifierReference(listOf(replaceFunc), functionCallExpr.target.position),
|
||||
functionCallExpr))
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
@ -144,3 +144,11 @@ func_all_f_stack .proc
|
||||
jsr a_times_5
|
||||
jmp prog8_lib.func_all_b_stack
|
||||
.pend
|
||||
|
||||
func_abs_f_into_FAC1 .proc
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr MOVFM
|
||||
jsr ABS
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
@ -86,16 +86,15 @@ func_all_w_stack .proc
|
||||
|
||||
abs_b_stack .proc
|
||||
; -- push abs(A) on stack (as unsigned word)
|
||||
jsr abs_b_into_AY
|
||||
jsr abs_b_into_A
|
||||
sta P8ESTACK_LO,x
|
||||
stz P8ESTACK_HI,x
|
||||
dex
|
||||
rts
|
||||
.pend
|
||||
|
||||
abs_b_into_AY .proc
|
||||
; -- AY = abs(A) (abs always returns unsigned word)
|
||||
ldy #0
|
||||
abs_b_into_A .proc
|
||||
; -- A = abs(A)
|
||||
cmp #0
|
||||
bmi +
|
||||
rts
|
||||
|
@ -532,7 +532,7 @@ class TestOptimization: FunSpec({
|
||||
uword @shared zz
|
||||
zz += 60 ; NOT ok to remove initializer, should evaluate to 60
|
||||
ubyte @shared xx
|
||||
xx = 6+lsb(abs(xx)) ; is not an initializer because it references xx
|
||||
xx = 6+lsb(mkword(xx,22)) ; is not an initializer because it references xx
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
@ -27,14 +27,14 @@ class TestTypecasts: FunSpec({
|
||||
main {
|
||||
sub start() {
|
||||
float fl
|
||||
floats.print_f(abs(fl))
|
||||
floats.print_f(lsb(fl))
|
||||
}
|
||||
}"""
|
||||
val errors = ErrorReporterForTests()
|
||||
val result = compileText(C64Target(), false, text, writeAssembly = false, errors=errors)
|
||||
result shouldBe null
|
||||
errors.errors.size shouldBe 1
|
||||
errors.errors[0] shouldContain "type mismatch, was: FLOAT expected one of: [UBYTE, BYTE, UWORD, WORD]"
|
||||
errors.errors[0] shouldContain "type mismatch, was: FLOAT expected one of: [UWORD, WORD]"
|
||||
}
|
||||
|
||||
test("not casting bool operands to logical operators") {
|
||||
|
@ -50,11 +50,11 @@ sys (part of syslib)
|
||||
- 16 = compiled for Commander X16 with 65C02 CPU
|
||||
- 64 = compiled for Commodore 64 with 6502/6510 CPU
|
||||
|
||||
``exit(returncode)``
|
||||
``exit (returncode)``
|
||||
Immediately stops the program and exits it, with the returncode in the A register.
|
||||
Note: custom interrupt handlers remain active unless manually cleared first!
|
||||
|
||||
``memcopy(from, to, numbytes)``
|
||||
``memcopy (from, to, numbytes)``
|
||||
Efficiently copy a number of bytes from a memory location to another.
|
||||
*Warning:* can only copy *non-overlapping* memory areas correctly!
|
||||
Because this function imposes some overhead to handle the parameters,
|
||||
@ -62,60 +62,60 @@ sys (part of syslib)
|
||||
Compare the generated code to see if it was beneficial or not.
|
||||
The most efficient will often be to write a specialized copy routine in assembly yourself!
|
||||
|
||||
``memset(address, numbytes, bytevalue)``
|
||||
``memset (address, numbytes, bytevalue)``
|
||||
Efficiently set a part of memory to the given (u)byte value.
|
||||
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
||||
Note that for clearing the screen, very fast specialized subroutines are
|
||||
available in the ``textio`` and ``graphics`` library modules.
|
||||
|
||||
``memsetw(address, numwords, wordvalue)``
|
||||
``memsetw (address, numwords, wordvalue)``
|
||||
Efficiently set a part of memory to the given (u)word value.
|
||||
But the most efficient will always be to write a specialized fill routine in assembly yourself!
|
||||
|
||||
``read_flags() -> ubyte``
|
||||
``read_flags () -> ubyte``
|
||||
Returns the current value of the CPU status register.
|
||||
|
||||
``set_carry()``
|
||||
``set_carry ()``
|
||||
Sets the CPU status register Carry flag.
|
||||
|
||||
``clear_carry()``
|
||||
``clear_carry ()``
|
||||
Clears the CPU status register Carry flag.
|
||||
|
||||
``set_irqd()``
|
||||
``set_irqd ()``
|
||||
Sets the CPU status register Interrupt Disable flag.
|
||||
|
||||
``clear_irqd()``
|
||||
``clear_irqd ()``
|
||||
Clears the CPU status register Interrupt Disable flag.
|
||||
|
||||
``progend()``
|
||||
``progend ()``
|
||||
Returns the last address of the program in memory + 1.
|
||||
Can be used to load dynamic data after the program, instead of hardcoding something.
|
||||
|
||||
``wait(uword jiffies)``
|
||||
``wait (uword jiffies)``
|
||||
wait approximately the given number of jiffies (1/60th seconds)
|
||||
Note: the regular system irq handler has run for this to work as it depends on the system jiffy clock.
|
||||
If this is is not possible (for instance because your program is running its own irq handler logic *and* no longer calls
|
||||
the kernal's handler routine), you'll have to write your own wait routine instead.
|
||||
|
||||
``waitvsync()``
|
||||
``waitvsync ()``
|
||||
busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
||||
can be used to avoid screen flicker/tearing when updating screen contents.
|
||||
note: a more accurate way to wait for vsync is to set up a vsync irq handler instead.
|
||||
note for cx16: the regular system irq handler has to run for this to work (this is not required on C64 and C128)
|
||||
|
||||
``waitrastborder()`` (c64/c128 targets only)
|
||||
``waitrastborder ()`` (c64/c128 targets only)
|
||||
busy wait till the raster position has reached the bottom screen border (approximately)
|
||||
can be used to avoid screen flicker/tearing when updating screen contents.
|
||||
note: a more accurate way to do this is by using a raster irq handler instead.
|
||||
|
||||
``reset_system()``
|
||||
``reset_system ()``
|
||||
Soft-reset the system back to initial power-on BASIC prompt.
|
||||
(called automatically by Prog8 when the main subroutine returns and the program is not using basicsafe zeropage option)
|
||||
|
||||
``poweroff_system()`` (commander x16 only)
|
||||
``poweroff_system ()`` (commander x16 only)
|
||||
Powers down the computer.
|
||||
|
||||
``set_leds_brightness(ubyte activity, ubyte power)`` (commander x16 only)
|
||||
``set_leds_brightness (ubyte activity, ubyte power)`` (commander x16 only)
|
||||
Sets the brightness of the activity and power leds on the computer.
|
||||
|
||||
|
||||
@ -157,63 +157,63 @@ string
|
||||
------
|
||||
Provides string manipulation routines.
|
||||
|
||||
``length(str) -> ubyte length``
|
||||
``length (str) -> ubyte length``
|
||||
Number of bytes in the string. This value is determined during runtime and counts upto
|
||||
the first terminating 0 byte in the string, regardless of the size of the string during compilation time.
|
||||
Don't confuse this with ``len`` and ``sizeof``!
|
||||
|
||||
``left(source, length, target)``
|
||||
``left (source, length, target)``
|
||||
Copies the left side of the source string of the given length to target string.
|
||||
It is assumed the target string buffer is large enough to contain the result.
|
||||
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||
|
||||
``right(source, length, target)``
|
||||
``right (source, length, target)``
|
||||
Copies the right side of the source string of the given length to target string.
|
||||
It is assumed the target string buffer is large enough to contain the result.
|
||||
Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||
|
||||
``slice(source, start, length, target)``
|
||||
``slice (source, start, length, target)``
|
||||
Copies a segment from the source string, starting at the given index,
|
||||
and of the given length to target string.
|
||||
It is assumed the target string buffer is large enough to contain the result.
|
||||
Also, you have to make sure yourself that start and length are within bounds of the strings.
|
||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
||||
|
||||
``find(string, char) -> ubyte index + carry bit``
|
||||
``find (string, char) -> ubyte index + carry bit``
|
||||
Locates the first position of the given character in the string, returns carry bit set if found
|
||||
and the index in the string. Or 0+carry bit clear if the character was not found.
|
||||
|
||||
``compare(string1, string2) -> ubyte result``
|
||||
``compare (string1, string2) -> ubyte result``
|
||||
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
||||
Note that you can also directly compare strings and string values with each other
|
||||
using ``==``, ``<`` etcetera (it will use string.compare for you under water automatically).
|
||||
|
||||
``copy(from, to) -> ubyte length``
|
||||
``copy (from, to) -> ubyte length``
|
||||
Copy a string to another, overwriting that one. Returns the length of the string that was copied.
|
||||
Often you don't have to call this explicitly and can just write ``string1 = string2``
|
||||
but this function is useful if you're dealing with addresses for instance.
|
||||
|
||||
``lower(string)``
|
||||
``lower (string)``
|
||||
Lowercases the PETSCII-string in place.
|
||||
|
||||
``upper(string)``
|
||||
``upper (string)``
|
||||
Uppercases the PETSCII-string in place.
|
||||
|
||||
``lowerchar(char)``
|
||||
``lowerchar (char)``
|
||||
Returns lowercased character.
|
||||
|
||||
``upperchar(char)``
|
||||
``upperchar (char)``
|
||||
Returns uppercased character.
|
||||
|
||||
``startswith(string, prefix) -> bool``
|
||||
``startswith (string, prefix) -> bool``
|
||||
Returns true if string starts with prefix, otherwise false
|
||||
|
||||
``endswith(string, suffix) -> bool``
|
||||
``endswith (string, suffix) -> bool``
|
||||
Returns true if string ends with suffix, otherwise false
|
||||
|
||||
``pattern_match(string, pattern) -> ubyte`` (not on Virtual target)
|
||||
``pattern_match (string, pattern) -> ubyte`` (not on Virtual target)
|
||||
Returns 1 (true) if the string matches the pattern, 0 (false) if not.
|
||||
'?' in the pattern matches any one character. '*' in the pattern matches any substring.
|
||||
|
||||
@ -225,61 +225,65 @@ floats
|
||||
Floating point support is only available on c64, cx16 and virtual targets for now.
|
||||
|
||||
Provides definitions for the ROM/Kernal subroutines and utility routines dealing with floating
|
||||
point variables. This includes ``print_f``, the routine used to print floating point numbers,
|
||||
``fabs`` to get the absolute value of a floating point number, and a dozen or so floating point
|
||||
math routines.
|
||||
point variables. This includes ``print_f``, the routine used to print floating point numbers.
|
||||
|
||||
atan(x)
|
||||
``atan (x)``
|
||||
Arctangent.
|
||||
|
||||
ceil(x)
|
||||
``ceil (x)``
|
||||
Rounds the floating point up to an integer towards positive infinity.
|
||||
|
||||
cos(x)
|
||||
``cos (x)``
|
||||
Cosine.
|
||||
If you want a fast integer cosine, have a look at examples/cx16/sincos.p8
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
deg(x)
|
||||
``deg (x)``
|
||||
Radians to degrees.
|
||||
|
||||
floor (x)
|
||||
``fabs (x)``
|
||||
Returns the absolute value of x. Deprecated, just use the builtin ``abs(x)`` function instead.
|
||||
|
||||
``floor (x)``
|
||||
Rounds the floating point down to an integer towards minus infinity.
|
||||
|
||||
ln(x)
|
||||
``ln (x)``
|
||||
Natural logarithm (base e).
|
||||
|
||||
log2(x)
|
||||
``log2 (x)``
|
||||
Base 2 logarithm.
|
||||
|
||||
minf(x, y)
|
||||
``minf (x, y)``
|
||||
returns the smallest of x and y.
|
||||
|
||||
maxf(x, y)
|
||||
``maxf (x, y)``
|
||||
returns the largest of x and y.
|
||||
|
||||
rad(x)
|
||||
``print_f (x)``
|
||||
prints the floating point number x as a string.
|
||||
|
||||
``rad (x)``
|
||||
Degrees to radians.
|
||||
|
||||
round(x)
|
||||
``round (x)``
|
||||
Rounds the floating point to the closest integer.
|
||||
|
||||
sin(x)
|
||||
``sin (x)``
|
||||
Sine.
|
||||
If you want a fast integer sine, have a look at examples/cx16/sincos.p8
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
sqrtf(x)
|
||||
``sqrtf (x)``
|
||||
Floating point Square root.
|
||||
To do the reverse, squaring a floating point number, just write ``x*x``.
|
||||
|
||||
tan(x)
|
||||
``tan (x)``
|
||||
Tangent.
|
||||
|
||||
rndf()
|
||||
``rndf ()``
|
||||
returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence.
|
||||
|
||||
rndseedf(seed)
|
||||
``rndseedf (seed)``
|
||||
Sets a new seed for the float pseudo-RNG sequence. Use a negative non-zero number as seed value.
|
||||
|
||||
|
||||
@ -306,41 +310,41 @@ Usually a custom lookup table is the way to go if your application needs these,
|
||||
but perhaps the provided ones can be of service too.
|
||||
|
||||
|
||||
rnd()
|
||||
``rnd ()``
|
||||
Returns next random byte 0-255 from the pseudo-RNG sequence.
|
||||
|
||||
rndw()
|
||||
``rndw ()``
|
||||
Returns next random word 0-65535 from the pseudo-RNG sequence.
|
||||
|
||||
rndseed(uword seed1, uword seed2)
|
||||
``rndseed (uword seed1, uword seed2)``
|
||||
Sets a new seed for the pseudo-RNG sequence (both rnd and rndw). The seed consists of two words.
|
||||
Do not use zeros for the seed!
|
||||
|
||||
sin8u(x)
|
||||
``sin8u (x)``
|
||||
Fast 8-bit ubyte sine of angle 0..255, result is in range 0..255
|
||||
|
||||
sin8(x)
|
||||
``sin8 (x)``
|
||||
Fast 8-bit byte sine of angle 0..255, result is in range -127..127
|
||||
|
||||
sinr8u(x)
|
||||
``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)
|
||||
``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!
|
||||
|
||||
cos8u(x)
|
||||
``cos8u (x)``
|
||||
Fast 8-bit ubyte cosine of angle 0..255, result is in range 0..255
|
||||
|
||||
cos8(x)
|
||||
``cos8 (x)``
|
||||
Fast 8-bit byte cosine of angle 0..255, result is in range -127..127
|
||||
|
||||
cosr8u(x)
|
||||
``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)
|
||||
``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!
|
||||
|
||||
|
@ -762,8 +762,7 @@ Math
|
||||
^^^^
|
||||
|
||||
abs (x)
|
||||
Absolute value of an integer. Value returned is an unsigned word.
|
||||
For floating point numbers, use ``floats.fabs()`` instead.
|
||||
Returns the absolute value of a number.
|
||||
|
||||
min (x, y)
|
||||
Returns the smallest of x and y. Supported for integer types only, for floats use ``floats.minf()`` instead.
|
||||
|
@ -6,7 +6,8 @@ For 9.0 major changes
|
||||
- DONE: added min() max() builtin functions
|
||||
- DONE: added 'cbm' block in the syslib module that now contains all CBM compatible kernal routines and variables
|
||||
- DONE: rename sqrt16() to just sqrt(), rename floats.sqrt() to floats.sqrtf()
|
||||
- add "polymorphism" of min() and max() to several other builtin functions as well (abs, divmod, pop, push) Fix docs.
|
||||
- DONE: abs() now supports multiple datatypes including float. No need to use floats.fabs() anymore.
|
||||
- add "polymorphism" of min() and max() to several other builtin functions as well (divmod, pop, push) Fix docs.
|
||||
- 6502 codegen: see if we can let for loops skip the loop if startvar>endvar, without adding a lot of code size/duplicating the loop condition.
|
||||
It is documented behavior to now loop 'around' $00 but it's too easy to forget about!
|
||||
Lot of work because of so many special cases in ForLoopsAsmgen.....
|
||||
|
Loading…
Reference in New Issue
Block a user