mirror of
https://github.com/irmen/prog8.git
synced 2024-10-03 05:55:26 +00:00
sqrt() now works on multiple data types including float.
no need to use floats.sqrtf() anymore
This commit is contained in:
parent
38efe25c68
commit
06368ab0a1
@ -87,7 +87,10 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
// normal functions follow:
|
||||
"sizeof" to FSignature(true, listOf(FParam("object", DataType.values())), DataType.UBYTE),
|
||||
"sgn" to FSignature(true, listOf(FParam("value", NumericDatatypesNoBool)), DataType.BYTE),
|
||||
"sqrt" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD))), DataType.UBYTE),
|
||||
"sqrt" to FSignature(true, listOf(FParam("value", NumericDatatypesNoBool)), DataType.UBYTE),
|
||||
"sqrt__ubyte" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UBYTE))), DataType.UBYTE),
|
||||
"sqrt__uword" to FSignature(true, listOf(FParam("value", arrayOf(DataType.UWORD))), DataType.UBYTE),
|
||||
"sqrt__float" to FSignature(true, listOf(FParam("value", arrayOf(DataType.FLOAT))), DataType.FLOAT),
|
||||
"divmod" to FSignature(false, listOf(FParam("number", arrayOf(DataType.UBYTE)), FParam("divident", arrayOf(DataType.UBYTE)), FParam("division", arrayOf(DataType.UBYTE)), FParam("remainder", arrayOf(DataType.UBYTE))), null),
|
||||
"divmodw" to FSignature(false, listOf(FParam("number", arrayOf(DataType.UWORD)), FParam("divident", arrayOf(DataType.UWORD)), FParam("division", arrayOf(DataType.UWORD)), FParam("remainder", arrayOf(DataType.UWORD))), null),
|
||||
"any" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), DataType.UBYTE),
|
||||
|
@ -36,7 +36,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
"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)
|
||||
"sqrt__ubyte", "sqrt__uword", "sqrt__float" -> funcSqrt(fcall, resultToStack, resultRegister, sscope)
|
||||
"divmod" -> funcDivmod(fcall)
|
||||
"divmodw" -> funcDivmodW(fcall)
|
||||
"rol" -> funcRol(fcall)
|
||||
@ -301,13 +301,33 @@ 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")
|
||||
else {
|
||||
asmgen.out(" jsr prog8_lib.func_sqrt16_into_A")
|
||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
|
||||
when(fcall.type) {
|
||||
DataType.UBYTE -> {
|
||||
if(resultToStack)
|
||||
asmgen.out(" ldy #0 | jsr prog8_lib.func_sqrt16_stack")
|
||||
else {
|
||||
asmgen.out(" ldy #0 | jsr prog8_lib.func_sqrt16_into_A")
|
||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
|
||||
}
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
if(resultToStack)
|
||||
asmgen.out(" jsr prog8_lib.func_sqrt16_stack")
|
||||
else {
|
||||
asmgen.out(" jsr prog8_lib.func_sqrt16_into_A")
|
||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
if(resultToStack)
|
||||
throw AssemblyError("no support for sqrt float onto stack")
|
||||
else {
|
||||
asmgen.out(" jsr floats.func_sqrt_into_FAC1")
|
||||
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird dt")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
"abs__byte", "abs__word", "abs__float" -> funcAbs(call)
|
||||
"cmp" -> funcCmp(call)
|
||||
"sgn" -> funcSgn(call)
|
||||
"sqrt" -> funcSqrt(call)
|
||||
"sqrt__ubyte", "sqrt__uword", "sqrt__float" -> funcSqrt(call)
|
||||
"divmod" -> funcDivmod(call, IRDataType.BYTE)
|
||||
"divmodw" -> funcDivmod(call, IRDataType.WORD)
|
||||
"pop" -> funcPop(call)
|
||||
@ -236,7 +236,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
addToResult(result, tr, -1, tr.resultFpReg)
|
||||
val resultFpReg = codeGen.registers.nextFreeFloat()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.SQRT, IRDataType.FLOAT, fpReg1 = resultFpReg, reg2 = tr.resultFpReg)
|
||||
it += IRInstruction(Opcode.SQRT, IRDataType.FLOAT, fpReg1 = resultFpReg, fpReg2 = tr.resultFpReg)
|
||||
}
|
||||
return ExpressionCodeResult(result, IRDataType.FLOAT, -1, resultFpReg)
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err
|
||||
errors.err("min/max not supported for floats", functionCallExpr.position)
|
||||
return noModifications
|
||||
} else {
|
||||
errors.err("expected numeric arguments", functionCallExpr.position)
|
||||
errors.err("expected numeric arguments", functionCallExpr.args[0].position)
|
||||
return noModifications
|
||||
}
|
||||
return listOf(IAstModification.SetExpression({functionCallExpr.target = it as IdentifierReference},
|
||||
@ -112,7 +112,25 @@ class VarConstantValueTypeAdjuster(private val program: Program, private val err
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr, functionCallExpr.args[0], parent))
|
||||
}
|
||||
else -> {
|
||||
errors.err("expected numeric argument", functionCallExpr.position)
|
||||
errors.err("expected numeric argument", functionCallExpr.args[0].position)
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
return listOf(IAstModification.SetExpression({functionCallExpr.target = it as IdentifierReference},
|
||||
IdentifierReference(listOf(replaceFunc), functionCallExpr.target.position),
|
||||
functionCallExpr))
|
||||
}
|
||||
}
|
||||
else if(func==listOf("sqrt")) {
|
||||
val t1 = functionCallExpr.args[0].inferType(program)
|
||||
if(t1.isKnown) {
|
||||
val dt = t1.getOrElse { throw InternalCompilerException("invalid dt") }
|
||||
val replaceFunc = when(dt) {
|
||||
DataType.UBYTE -> "sqrt__ubyte"
|
||||
DataType.UWORD -> "sqrt__uword"
|
||||
DataType.FLOAT -> "sqrt__float"
|
||||
else -> {
|
||||
errors.err("expected unsigned or float numeric argument", functionCallExpr.args[0].position)
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
@ -152,3 +152,11 @@ func_abs_f_into_FAC1 .proc
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
||||
func_sqrt_into_FAC1 .proc
|
||||
stx P8ZP_SCRATCH_REG
|
||||
jsr MOVFM
|
||||
jsr SQR
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
rts
|
||||
.pend
|
||||
|
@ -16,7 +16,9 @@ internal val constEvaluatorsForBuiltinFuncs: Map<String, ConstExpressionCaller>
|
||||
"len" to ::builtinLen,
|
||||
"sizeof" to ::builtinSizeof,
|
||||
"sgn" to ::builtinSgn,
|
||||
"sqrt" to { a, p, prg -> oneIntArgOutputInt(a, p, prg) { sqrt(it.toDouble()) } },
|
||||
"sqrt__ubyte" to { a, p, prg -> oneIntArgOutputInt(a, p, prg) { sqrt(it.toDouble()) } },
|
||||
"sqrt__uword" to { a, p, prg -> oneIntArgOutputInt(a, p, prg) { sqrt(it.toDouble()) } },
|
||||
"sqrt__float" to { a, p, prg -> oneFloatArgOutputFloat(a, p, prg) { sqrt(it) } },
|
||||
"any" to { a, p, prg -> collectionArg(a, p, prg, ::builtinAny) },
|
||||
"all" to { a, p, prg -> collectionArg(a, p, prg, ::builtinAll) },
|
||||
"lsb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg) { x: Int -> (x and 255).toDouble() } },
|
||||
@ -64,6 +66,16 @@ private fun oneIntArgOutputInt(args: List<Expression>, position: Position, progr
|
||||
return NumericLiteral.optimalInteger(function(integer).toInt(), args[0].position)
|
||||
}
|
||||
|
||||
private fun oneFloatArgOutputFloat(args: List<Expression>, position: Position, program: Program, function: (arg: Double)->Double): NumericLiteral {
|
||||
if(args.size!=1)
|
||||
throw SyntaxError("built-in function requires one float argument", position)
|
||||
val constval = args[0].constValue(program) ?: throw NotConstArgumentException()
|
||||
if(constval.type != DataType.FLOAT)
|
||||
throw SyntaxError("built-in function requires one float argument", position)
|
||||
|
||||
return NumericLiteral(DataType.FLOAT, function(constval.number), args[0].position)
|
||||
}
|
||||
|
||||
private fun collectionArg(args: List<Expression>, position: Position, program: Program, function: (arg: List<Double>)->Double): NumericLiteral {
|
||||
if(args.size!=1)
|
||||
throw SyntaxError("builtin function requires one non-scalar argument", position)
|
||||
|
@ -242,7 +242,7 @@ point variables. This includes ``print_f``, the routine used to print floating
|
||||
Radians to degrees.
|
||||
|
||||
``fabs (x)``
|
||||
Returns the absolute value of x. Deprecated, just use the builtin ``abs(x)`` function instead.
|
||||
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.
|
||||
@ -274,7 +274,7 @@ point variables. This includes ``print_f``, the routine used to print floating
|
||||
that contains various lookup tables generated by the 64tass assembler.
|
||||
|
||||
``sqrtf (x)``
|
||||
Floating point Square root.
|
||||
Floating point Square root. Deprecated; just use the ``sqrt (x)`` builtin fuction instead.
|
||||
To do the reverse, squaring a floating point number, just write ``x*x``.
|
||||
|
||||
``tan (x)``
|
||||
|
@ -774,9 +774,9 @@ sgn (x)
|
||||
Get the sign of the value. Result is -1, 0 or 1 (negative, zero, positive).
|
||||
|
||||
sqrt (w)
|
||||
16 bit unsigned integer Square root. Result is unsigned byte.
|
||||
To do the reverse, squaring an integer, just write ``x*x``.
|
||||
Floating point square root has its own function `floats.sqrtf()`
|
||||
Returns the square root of the number.
|
||||
Supports unsigned integer (result is ubyte) and floating point numbers.
|
||||
To do the reverse - squaring a number - just write ``x*x``.
|
||||
|
||||
divmod (number, divident, division, remainder)
|
||||
Performs division and remainder calculation in a single call. This is faster than using separate '/' and '%' calculations.
|
||||
|
@ -5,7 +5,7 @@ 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()
|
||||
- DONE: rename sqrt16() to just sqrt(), make it accept multiple numeric types. Renamed floats.sqrt() to floats.sqrtf() but you can just use sqrt()
|
||||
- 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.
|
||||
|
Loading…
Reference in New Issue
Block a user