Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add graphing calculator #45

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/java/net/youapps/calcyou/Destination.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ sealed class Destination(open val route: String) {

object Converters : Destination("converters")
object CharacterInput : Destination("character_input")
object Graphing : Destination("graphing")
sealed class Converter(
override val route: String,
@StringRes val resId: Int,
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/net/youapps/calcyou/NavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import net.youapps.calcyou.ui.CalculatorScreen
import net.youapps.calcyou.ui.screens.CharacterInputScreen
import net.youapps.calcyou.ui.screens.ConverterGridScreen
import net.youapps.calcyou.ui.screens.ConverterScreen
import net.youapps.calcyou.ui.screens.graphing.GraphingScreen

@Composable
fun AppNavHost(modifier: Modifier = Modifier, navHostController: NavHostController) {
Expand All @@ -31,6 +32,10 @@ fun AppNavHost(modifier: Modifier = Modifier, navHostController: NavHostControll
CharacterInputScreen()
}

composable(route = Destination.Graphing.route) {
GraphingScreen()
}

Destination.Converter.values.forEach { converter ->
composable(route = converter.route) {
ConverterScreen(converter = converter.converter, converterName = converter.resId)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
This code is a modified version of https://github.com/danielgindi/KotlinEval
The original source code is licensed under MIT LICENSE
*/

package net.youapps.calcyou.data.graphing

class CompiledExpression internal constructor(
internal var root: Token,
var configuration: EvalConfiguration
) {
fun execute(): Double? =
Evaluator.execute(expression = this)

fun execute(constant: Pair<String, Double>): Double? =
Evaluator.execute(this, constant)

fun setConstant(name: String, value: Double) {
configuration.setConstant(name = name, value = value)
}

fun removeConstant(name: String) {
configuration.removeConstant(name = name)
}

fun setFunction(name: String, func: EvalFunctionBlock) {
configuration.setFunction(name = name, func = func)
}

fun removeFunction(name: String) {
configuration.removeFunction(name = name)
}

fun clearConstants() {
configuration.clearConstants()
}

fun clearFunctions() {
configuration.clearConstants()
}
}
157 changes: 157 additions & 0 deletions app/src/main/java/net/youapps/calcyou/data/graphing/Defaults.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
This code is a modified version of https://github.com/danielgindi/KotlinEval
The original source code is licensed under MIT LICENSE
*/

package net.youapps.calcyou.data.graphing

import java.security.InvalidParameterException
import kotlin.math.abs
import kotlin.math.acos
import kotlin.math.asin
import kotlin.math.atan
import kotlin.math.atan2
import kotlin.math.ceil
import kotlin.math.cos
import kotlin.math.cosh
import kotlin.math.exp
import kotlin.math.floor
import kotlin.math.ln
import kotlin.math.log
import kotlin.math.log10
import kotlin.math.log2
import kotlin.math.pow
import kotlin.math.round
import kotlin.math.sin
import kotlin.math.sinh
import kotlin.math.sqrt
import kotlin.math.tan
import kotlin.math.tanh
import kotlin.math.truncate

object Defaults {
val defaultOperatorOrder: List<List<Operator>> = listOf(
listOf(Operator.POW),
listOf(Operator.DIV, Operator.MUL, Operator.MOD),
listOf(Operator.SUB, Operator.ADD),
)
val defaultRightAssociativeOps: Set<String> = setOf("**")
val defaultGenericConstants: Map<String, Double> = mapOf(
"PI" to Math.PI,
"PI_2" to Math.PI / 2,
"LOG2E" to log2(Math.E),
"DEG" to Math.PI / 180f,
"E" to Math.E
)
val defaultVarNameChars: Set<Char> =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$".toCharArray().toSet()

fun getDefaultGenericFunctions(): Map<String, EvalFunctionBlock> {
return mapOf(
"ABS" to { args ->
abs(args.first())
},
"ACOS" to { args ->

acos(args.first())
},
"ASIN" to { args ->

asin(args.first())
},
"ATAN" to { args ->

atan(args.first())
},
"ATAN2" to { args ->
val arg1 = args[0]
val arg2 = args[1]
if (args.size != 2) {
throw InvalidParameterException()
}
atan2(arg1, arg2)
},
"CEILING" to { args ->
ceil(args.first())
},
"COS" to { args ->
cos(args.first())
},
"COSH" to { args ->
cosh(args.first())
},
"EXP" to { args ->
exp(args.first())
},
"FLOOR" to { args ->
floor(args.first())
},
"LOG" to fn@{ args ->
if (args.size == 2) {
val arg1 = args[0]
val arg2 = args[1]

return@fn log(arg1, arg2)
} else if (args.size == 1) {
return@fn ln(args.first())
}
throw InvalidParameterException()
},
"LOG2" to { args ->
log2(args.first())
},
"LOG10" to { args ->
log10(args.first())
},
"MAX" to fn@{ args ->
var v = args[0]
for (arg in args) {
val narg = arg
if (narg > v)
v = narg
}
v
},
"MIN" to fn@{ args ->
var v = args[0]
for (arg in args) {
val narg = arg
if (narg < v)
v = narg
}
v
},
"POW" to fn@{ args ->
if (args.size == 2) {
val arg1 = args[0]
val arg2 = args[1]
return@fn arg1.pow(arg2)
}
throw InvalidParameterException()
},
"ROUND" to { args ->
round(args.first())
},
"SIGN" to { args ->
if (args.first() < 0) -1.0 else if (args.first() > 0) 1.0 else 0.0
},
"SIN" to { args ->
sin(args.first())
},
"SINH" to { args ->
sinh(args.first())
},
"SQRT" to { args ->
sqrt(args.first())
},
"TAN" to { args ->
tan(args.first())
},
"TANH" to { args ->
tanh(args.first())
},
"TRUNCATE" to { args ->
truncate(args.first())
})
}
}
87 changes: 87 additions & 0 deletions app/src/main/java/net/youapps/calcyou/data/graphing/EvalConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
This code is a modified version of https://github.com/danielgindi/KotlinEval
The original source code is licensed under MIT LICENSE
*/

package net.youapps.calcyou.data.graphing

typealias EvalFunctionBlock = (args: List<Double>) -> Double

class EvalConfiguration(
var constants: MutableMap<String, Double>? = null,
var functions: MutableMap<String, EvalFunctionBlock>? = null
) {

internal var allOperators = listOf<Operator>()
private var _operatorOrder = listOf<List<Operator>>()
var operatorOrder: List<List<Operator>>
get() {
return _operatorOrder
}
set(newValue) {
val ops = mutableListOf<Operator>()
for (ops2 in newValue)
ops.addAll(ops2)

_operatorOrder = newValue
allOperators = ops
}

var rightAssociativeOps = setOf<String>()

var varNameChars = setOf<Char>()

var genericConstants = mutableMapOf<String, Double>()
var genericFunctions = mutableMapOf<String, EvalFunctionBlock>()

@Suppress("unused")
fun setConstant(name: String, value: Double) {
if (constants == null) {
constants = mutableMapOf()
}
constants!![name] = value
}

@Suppress("unused")
fun removeConstant(name: String) {
if (constants == null) {
return
}
constants?.remove(name)
}

@Suppress("unused")
fun setFunction(name: String, func: EvalFunctionBlock) {
if (functions == null) {
functions = mutableMapOf()
}
functions!![name] = func
}

@Suppress("unused")
fun removeFunction(name: String) {
if (functions == null) {
return
}
functions?.remove(name)
}

@Suppress("unused")
fun clearConstants() {
constants?.clear()
}

@Suppress("unused")
fun clearFunctions() {
functions?.clear()
}

init {
this.operatorOrder = Defaults.defaultOperatorOrder
this.rightAssociativeOps = Defaults.defaultRightAssociativeOps
this.varNameChars = Defaults.defaultVarNameChars
this.genericConstants = Defaults.defaultGenericConstants.toMutableMap()
this.genericFunctions = Defaults.getDefaultGenericFunctions().toMutableMap()

}
}
Loading