Skip to content

Commit

Permalink
Merge pull request #45 from you-apps/graphing
Browse files Browse the repository at this point in the history
add graphing calculator
  • Loading branch information
SuhasDissa authored May 8, 2024
2 parents 93a7506 + 46d358f commit 0e58340
Show file tree
Hide file tree
Showing 19 changed files with 2,091 additions and 1 deletion.
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

0 comments on commit 0e58340

Please sign in to comment.