Skip to content

Instantly share code, notes, and snippets.

@killjoy1221
Created December 12, 2018 03:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save killjoy1221/02c3f1b83b0e6afad731cce616f3f97e to your computer and use it in GitHub Desktop.
Save killjoy1221/02c3f1b83b0e6afad731cce616f3f97e to your computer and use it in GitHub Desktop.
import kotlin.math.pow
import kotlin.math.sqrt
import kotlin.reflect.full.primaryConstructor
interface Maths<Num : Number> {
fun plus(a: Num, b: Num): Num
fun minus(a: Num, b: Num): Num
fun times(a: Num, b: Num): Num
fun div(a: Num, b: Num): Num
fun pow(a: Num, b: Num): Num
fun abs(a: Num): Num
fun toType(a: Number): Num
}
object IntMaths : Maths<Int> {
override fun plus(a: Int, b: Int) = a + b
override fun minus(a: Int, b: Int) = a - b
override fun times(a: Int, b: Int) = a * b
override fun div(a: Int, b: Int) = a / b
override fun pow(a: Int, b: Int) = a.toDouble().pow(b).toInt()
override fun abs(a: Int) = kotlin.math.abs(a)
override fun toType(a: Number) = a.toInt()
}
object DoubleMaths : Maths<Double> {
override fun plus(a: Double, b: Double) = a + b
override fun minus(a: Double, b: Double) = a - b
override fun times(a: Double, b: Double) = a * b
override fun div(a: Double, b: Double) = a / b
override fun pow(a: Double, b: Double) = a.pow(b)
override fun abs(a: Double) = kotlin.math.abs(a)
override fun toType(a: Number) = a.toDouble()
}
data class Vec2i(override val x: Int, override val y: Int) : Vec2<Int>(IntMaths)
data class Vec2d(override val x: Double, override val y: Double) : Vec2<Double>(DoubleMaths)
sealed class Vec2<N : Number>(private val maths: Maths<N>) {
abstract val x: N
abstract val y: N
fun plus(x: N, y: N = x) = new(this.x + x, this.y + y)
fun minus(x: N, y: N = x) = new(this.x - x, this.y - y)
fun times(x: N, y: N = x) = new(this.x * x, this.y * y)
fun div(x: N, y: N = x) = new(this.x / x, this.y / y)
fun length(x: N, y: N) = maths.abs(y - this.y) + maths.abs(x - this.x)
fun distSq(x: N, y: N) = (this.x - x).pow(!2) + (this.y - y).pow(!2)
fun dist(x: N, y: N) = sqrt(distSq(x, y).toDouble())
fun length(other: Vec2<N>) = length(other.x, other.y)
fun distSq(other: Vec2<N>) = distSq(other.x, other.y)
fun dist(other: Vec2<N>) = dist(other.x, other.y)
operator fun plus(other: Vec2<N>) = plus(other.x, other.y)
operator fun minus(other: Vec2<N>) = minus(other.x, other.y)
operator fun times(other: Vec2<N>) = times(other.x, other.y)
operator fun div(other: Vec2<N>) = div(other.x, other.y)
operator fun unaryMinus() = times(!-1)
operator fun unaryPlus() = this
fun toVec2i() = this as? Vec2i ?: Vec2i(x.toInt(), y.toInt())
fun toVec2d() = this as? Vec2d ?: Vec2d(x.toDouble(), y.toDouble())
private fun new(x: Number, y: Number) = this::class.primaryConstructor!!.call(!x, !y)
private operator fun N.plus(a: N) = maths.plus(this, a)
private operator fun N.minus(a: N) = maths.minus(this, a)
private operator fun N.times(a: N) = maths.times(this, a)
private operator fun N.div(a: N) = maths.div(this, a)
private operator fun Number.not(): N = maths.toType(this)
private fun N.pow(a: N) = maths.pow(this, a)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment