diff --git a/README.md b/README.md index bd09df3..b9f0894 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The name will be in the format "exact-numbers-version", where the version is spe This app has a dependency on the [kotlin-utils](https://github.com/lbressler13/kotlin-utils) package, which is published to the GitHub Packages registry. In order to build the project, you will need a GitHub access token with at least the `read:packages` scope. -You can add the following properties to a gradle.properties file in order to build: +You can add the following properties to a local gradle properties file in order to build: ```properties gpr.user=GITHUB_USERNAME gpr.key=GITHUB_PAT diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFraction.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFraction.kt index d109f30..5827fc0 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFraction.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFraction.kt @@ -79,9 +79,9 @@ sealed class ExactFraction : Comparable, Number() { abstract fun isWholeNumber(): Boolean /** - * Round ExactFraction to nearest whole number. + * Round to nearest whole number * - * @param roundingMode [RoundingMode]: mode to use for rounding number. Optional, defaults to [RoundingMode.HALF_UP] + * @param roundingMode [RoundingMode]: mode to use for rounding number. Defaults to [RoundingMode.HALF_UP] */ abstract fun roundToWhole(roundingMode: RoundingMode = RoundingMode.HALF_UP): ExactFraction @@ -90,8 +90,7 @@ sealed class ExactFraction : Comparable, Number() { /** * Create a string representation in standard decimal format * - * @param digits [Int]: digits of precision in string. Defaults to 8. - * Will be ignored if this number results in a string in exponential format + * @param digits [Int]: maximum number of digits after decimal point. Defaults to 8 * @return [String]: representation in decimal format */ abstract fun toDecimalString(digits: Int = 8): String diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFractionOverflowException.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFractionOverflowException.kt index 7adcccf..4bd8e19 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFractionOverflowException.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/ExactFractionOverflowException.kt @@ -4,7 +4,11 @@ package xyz.lbres.exactnumbers.exactfraction * [ArithmeticException] for ExactFraction overflow. * Has field for string representation of value that caused overflow */ -class ExactFractionOverflowException private constructor(message: String?, overflowValue: String?, noArgs: Boolean) : ArithmeticException() { +class ExactFractionOverflowException private constructor( + message: String?, + overflowValue: String?, + noArgsConstructor: Boolean +) : ArithmeticException() { override val message: String? val overflowValue: String? @@ -13,9 +17,9 @@ class ExactFractionOverflowException private constructor(message: String?, overf this.overflowValue = overflowValue } - constructor() : this(null, null, true) + constructor() : this(null, null, noArgsConstructor = true) - constructor(message: String) : this(message, null, false) + constructor(message: String) : this(message, null, noArgsConstructor = false) - constructor(message: String, overflowValue: String) : this(message, overflowValue, false) + constructor(message: String, overflowValue: String) : this(message, overflowValue, noArgsConstructor = false) } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionConstructors.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionConstructors.kt index d935ffa..05f8d5f 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionConstructors.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionConstructors.kt @@ -14,77 +14,77 @@ fun ExactFraction(numerator: BigInteger, denominator: BigInteger): ExactFraction * @param numerator [Int] * @param denominator [Int] */ -fun ExactFraction(numerator: Int, denominator: Int): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), denominator.toBigInteger()) +fun ExactFraction(numerator: Int, denominator: Int): ExactFraction = ExactFraction(numerator.toBigInteger(), denominator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator and denominator * @param numerator [Long] * @param denominator [Long] */ -fun ExactFraction(numerator: Long, denominator: Long): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), denominator.toBigInteger()) +fun ExactFraction(numerator: Long, denominator: Long): ExactFraction = ExactFraction(numerator.toBigInteger(), denominator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator and denominator - * @param numerator [Int] - * @param denominator [Long] + * @param numerator [Long] + * @param denominator [Int] */ -fun ExactFraction(numerator: Long, denominator: Int): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), denominator.toBigInteger()) +fun ExactFraction(numerator: Long, denominator: Int): ExactFraction = ExactFraction(numerator.toBigInteger(), denominator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator and denominator * @param numerator [Int] * @param denominator [Long] */ -fun ExactFraction(numerator: Int, denominator: Long): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), denominator.toBigInteger()) +fun ExactFraction(numerator: Int, denominator: Long): ExactFraction = ExactFraction(numerator.toBigInteger(), denominator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator and denominator * @param numerator [BigInteger] - * @param denominator [Long] + * @param denominator [Int] */ -fun ExactFraction(numerator: BigInteger, denominator: Int): ExactFraction = ExactFractionImpl(numerator, denominator.toBigInteger()) +fun ExactFraction(numerator: BigInteger, denominator: Int): ExactFraction = ExactFraction(numerator, denominator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator and denominator * @param numerator [Int] * @param denominator [BigInteger] */ -fun ExactFraction(numerator: Int, denominator: BigInteger): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), denominator) +fun ExactFraction(numerator: Int, denominator: BigInteger): ExactFraction = ExactFraction(numerator.toBigInteger(), denominator) /** * Construct an ExactFraction by specifying numerator and denominator * @param numerator [BigInteger] * @param denominator [Long] */ -fun ExactFraction(numerator: BigInteger, denominator: Long): ExactFraction = ExactFractionImpl(numerator, denominator.toBigInteger()) +fun ExactFraction(numerator: BigInteger, denominator: Long): ExactFraction = ExactFraction(numerator, denominator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator and denominator * @param numerator [Long] * @param denominator [BigInteger] */ -fun ExactFraction(numerator: Long, denominator: BigInteger): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), denominator) +fun ExactFraction(numerator: Long, denominator: BigInteger): ExactFraction = ExactFraction(numerator.toBigInteger(), denominator) /** * Construct an ExactFraction by specifying numerator only * @param numerator [BigInteger] */ -fun ExactFraction(numerator: BigInteger): ExactFraction = ExactFractionImpl(numerator, BigInteger.ONE) +fun ExactFraction(numerator: BigInteger): ExactFraction = ExactFraction(numerator, BigInteger.ONE) /** * Construct an ExactFraction by specifying numerator only * @param numerator [Int] */ -fun ExactFraction(numerator: Int): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), BigInteger.ONE) +fun ExactFraction(numerator: Int): ExactFraction = ExactFraction(numerator.toBigInteger()) /** * Construct an ExactFraction by specifying numerator only * @param numerator [Long] */ -fun ExactFraction(numerator: Long): ExactFraction = ExactFractionImpl(numerator.toBigInteger(), BigInteger.ONE) +fun ExactFraction(numerator: Long): ExactFraction = ExactFraction(numerator.toBigInteger()) /** - * Construct ExactFraction by parsing a string + * Construct ExactFraction by parsing an EF-format or decimal string * @param string [String] */ fun ExactFraction(string: String): ExactFraction = ExactFraction.parse(string) diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionHelpers.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionHelpers.kt index aeec2b4..19c58be 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionHelpers.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionHelpers.kt @@ -38,8 +38,7 @@ internal fun simplifyFraction(numerator: BigInteger, denominator: BigInteger): T * Create a string representation of an [ExactFraction] in standard decimal format * * @param ef [ExactFraction]: number to convert to string - * @param digits [Int]: digits of precision in string. Must be non-negative. - * Will be ignored if this number results in a string in exponential format. + * @param digits [Int]: maximum number of digits after decimal point. Must be non-negative * @return [String]: representation in decimal format */ internal fun createDecimalString(ef: ExactFraction, digits: Int): String { diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionParsing.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionParsing.kt index 5f9c8ad..19d5bf4 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionParsing.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exactfraction/exactFractionParsing.kt @@ -2,7 +2,7 @@ package xyz.lbres.exactnumbers.exactfraction import xyz.lbres.kotlinutils.general.simpleIf import xyz.lbres.kotlinutils.general.succeeds -import xyz.lbres.kotlinutils.general.tryOrDefault +import xyz.lbres.kotlinutils.string.ext.isInt import java.math.BigDecimal import java.math.BigInteger @@ -86,16 +86,6 @@ internal fun checkIsEFString(s: String): Boolean { return false } - return tryOrDefault(false) { - val numbers = trimmed.substring(efPrefix.length, s.length - efSuffix.length).split(' ') - val validNumber: (String) -> Boolean = { - when { - it.isEmpty() -> false - it.length == 1 -> it[0].isDigit() - else -> (it[0] == '-' || it[0].isDigit()) && it.substring(1).all(Char::isDigit) - } - } - - numbers.size == 2 && validNumber(numbers[0]) && validNumber(numbers[1]) - } + val numbers = trimmed.substring(efPrefix.length, s.length - efSuffix.length).split(' ') + return numbers.size == 2 && numbers[0].isInt() && numbers[1].isInt() } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exceptions/CastingOverflowException.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exceptions/CastingOverflowException.kt index 38e3358..2d59d2c 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exceptions/CastingOverflowException.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/exceptions/CastingOverflowException.kt @@ -7,23 +7,20 @@ class CastingOverflowException private constructor( baseType: String, targetType: String, valueString: String, - overflowValue: Any?, - noArgs: Boolean + val overflowValue: Any?, + noArgsConstructor: Boolean ) : ArithmeticException() { override val message: String? - val overflowValue: Any? init { - if (noArgs) { - this.message = null - this.overflowValue = null + this.message = if (noArgsConstructor) { + null } else { - this.message = "Overflow casting value $valueString of type $baseType to $targetType" - this.overflowValue = overflowValue + "Overflow casting value $valueString of type $baseType to $targetType" } } - constructor() : this("", "", "", null, true) + constructor() : this("", "", "", null, noArgsConstructor = true) /** * @param baseType [String]: name of type being cast from @@ -32,5 +29,5 @@ class CastingOverflowException private constructor( * @param overflowValue [Any]?: number that caused overflow. Optional, defaults to `null` */ constructor (baseType: String, targetType: String, valueString: String, overflowValue: Any? = null) : - this(baseType, targetType, valueString, overflowValue, false) + this(baseType, targetType, valueString, overflowValue, noArgsConstructor = false) } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/Term.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/Term.kt index 49937f8..a625c51 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/Term.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/Term.kt @@ -17,6 +17,7 @@ import xyz.lbres.exactnumbers.utils.irrationalsPackage import xyz.lbres.kotlinutils.collection.ext.toConstMultiSet import xyz.lbres.kotlinutils.general.simpleIf import xyz.lbres.kotlinutils.iterable.ext.countElement +import xyz.lbres.kotlinutils.list.listOfValue import java.math.BigDecimal import kotlin.math.abs @@ -100,13 +101,13 @@ sealed class Term : Number() { * @param coefficient [ExactFraction] * @param logs [List]: list of log numbers * @param roots [List]: list of square root numbers - * @param piCount [Int]: how many occurrence of Pi to include in the list of numbers. - * A negative number corresponds to divided Pi values + * @param piCount [Int]: how many occurrences of pi to include in the list of numbers. + * A negative number corresponds to Pi values where inverted is `true` * @return [Term] with the given values */ fun fromValues(coefficient: ExactFraction, logs: List, roots: List, piCount: Int): Term { - val pis = List(abs(piCount)) { simpleIf(piCount < 0, { Pi().inverse() }, { Pi() }) } - return fromValues(coefficient, logs + roots + pis) + val pi = simpleIf(piCount < 0, Pi().inverse(), Pi()) + return fromValues(coefficient, logs + roots + listOfValue(abs(piCount), pi)) } } } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/TermImpl.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/TermImpl.kt index d05c6e9..f1671a2 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/TermImpl.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/TermImpl.kt @@ -10,7 +10,7 @@ import xyz.lbres.kotlinutils.general.simpleIf import xyz.lbres.kotlinutils.set.multiset.anyConsistent import xyz.lbres.kotlinutils.set.multiset.const.ConstMultiSet import xyz.lbres.kotlinutils.set.multiset.const.emptyConstMultiSet -import xyz.lbres.kotlinutils.set.multiset.mapToSetConsistent +import xyz.lbres.kotlinutils.set.multiset.mapToSet import java.math.BigDecimal // implementation of Term class @@ -47,8 +47,8 @@ internal class TermImpl(coefficient: ExactFraction, factors: ConstMultiSet", "<${coeffString}x$factorString>") - string = result + string = simpleIf(factorString.isEmpty(), "<$coeffString>", "<${coeffString}x$factorString>") } return string!! diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/helpers.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/helpers.kt index 62c86f1..7998379 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/helpers.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/expressions/term/helpers.kt @@ -47,7 +47,7 @@ internal fun createSimplifiedTerm(coefficient: ExactFraction, factorGroups: Map< /** * Simplify a set of irrational numbers by extracting the rational values * - * @param values [ConstMultiSet]>: list of values + * @param values [ConstMultiSet]>: list of values, which are assumed to have the same type * @return [Pair]>: pair of values where first value is the product of the numbers * with rational values, and the second is a set of the irrational values */ diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExt.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExt.kt index bfc1853..feaa57b 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExt.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExt.kt @@ -1,6 +1,7 @@ package xyz.lbres.exactnumbers.ext import xyz.lbres.exactnumbers.utils.divideByZero +import xyz.lbres.kotlinutils.general.succeeds import java.math.BigDecimal import java.math.MathContext @@ -22,3 +23,10 @@ internal fun BigDecimal.divideBy(other: BigDecimal): BigDecimal { divide(other, mc) } } + +/** + * Determine if decimal is a whole number + * + * @return `true` if number is a whole number, `false` otherwise + */ +internal fun BigDecimal.isWholeNumber(): Boolean = succeeds { toBigIntegerExact() } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/IrrationalNumber.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/IrrationalNumber.kt index be5f0d1..c479876 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/IrrationalNumber.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/IrrationalNumber.kt @@ -19,7 +19,7 @@ import java.math.BigDecimal */ abstract class IrrationalNumber> : Comparable, Number() { /** - * Type of number, should correspond to the type name for the class + * Type of number */ abstract val type: String @@ -28,7 +28,7 @@ abstract class IrrationalNumber> : Comparable, Number */ abstract val isInverted: Boolean @Deprecated("Property $deprecatedV1", ReplaceWith("isInverted"), DeprecationLevel.WARNING) - val isDivided: Boolean + val isDivided: Boolean // maintained from Irrational interface get() = isInverted /** @@ -57,7 +57,7 @@ abstract class IrrationalNumber> : Comparable, Number abstract fun inverse(): T @Deprecated("Method $deprecatedV1", ReplaceWith("inverse"), DeprecationLevel.WARNING) - fun swapDivided(): T = inverse() + fun swapDivided(): T = inverse() // maintained from Irrational interface operator fun times(other: IrrationalNumber<*>): Term = Term.fromValues(ExactFraction.ONE, listOf(this, other)) operator fun times(other: ExactFraction): Term = Term.fromValues(other, listOf(this)) @@ -89,7 +89,6 @@ abstract class IrrationalNumber> : Comparable, Number override fun toShort(): Short = castToShort(getValue(), this, type) override fun toInt(): Int = castToInt(getValue(), this, type) override fun toLong(): Long = castToLong(getValue(), this, type) - override fun toFloat(): Float = castToFloat(getValue(), this, type) override fun toDouble(): Double = castToDouble(getValue(), this, type) diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/Log.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/Log.kt index 26472b9..b3df73d 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/Log.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/Log.kt @@ -60,8 +60,7 @@ sealed class Log : IrrationalNumber() { if (log != ONE) { val diff = logValues.getCountOf(log) - logValues.getCountOf(log.inverse()) val valueToAdd = simpleIf(diff < 0, { log.inverse() }, { log }) - val simplified: ConstMultiSet = ConstMultiSet(abs(diff)) { valueToAdd } - simplifiedValues.addAll(simplified) + repeat(abs(diff)) { simplifiedValues.add(valueToAdd) } } } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogImpl.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogImpl.kt index dd479bc..20efcf6 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogImpl.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogImpl.kt @@ -2,6 +2,7 @@ package xyz.lbres.exactnumbers.irrationals.log import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.ext.divideBy +import xyz.lbres.exactnumbers.ext.isWholeNumber import xyz.lbres.exactnumbers.utils.createHashCode import xyz.lbres.exactnumbers.utils.divideByZero import xyz.lbres.kotlinutils.biginteger.ext.isZero @@ -18,8 +19,8 @@ internal class LogImpl private constructor( ) : Log() { override val type = TYPE - private var numLog: BigDecimal? = null - private var denomLog: BigDecimal? = null + private var numeratorLog: BigDecimal? = null + private var denominatorLog: BigDecimal? = null private var simplified: Pair? = null init { @@ -38,7 +39,7 @@ internal class LogImpl private constructor( override fun isRational(): Boolean { setLogs() // rational if both values are whole numbers - return !numLog!!.toPlainString().contains('.') && !denomLog!!.toPlainString().contains('.') + return numeratorLog!!.isWholeNumber() && denominatorLog!!.isWholeNumber() } override fun getRationalValue(): ExactFraction? { @@ -48,8 +49,8 @@ internal class LogImpl private constructor( } setLogs() - val numInt = numLog!!.toBigInteger() - val denomInt = denomLog!!.toBigInteger() + val numInt = numeratorLog!!.toBigInteger() + val denomInt = denominatorLog!!.toBigInteger() val result = when { numInt.isZero() -> -ExactFraction(denomInt) // numerator of argument is 1 @@ -60,10 +61,10 @@ internal class LogImpl private constructor( return simpleIf(isInverted, { result.inverse() }, { result }) } - // uses the formula log_b(x/y) = log_b(x) - log_b(y) to reduce loss of precision when casting to Double + // uses the formula log_b(x/y) = log_b(x) - log_b(y) to increase precision override fun getValue(): BigDecimal { setLogs() - val logValue = numLog!! - denomLog!! + val logValue = numeratorLog!! - denominatorLog!! return simpleIf(isInverted, { BigDecimal.ONE.divideBy(logValue) }, { logValue }) } @@ -90,9 +91,9 @@ internal class LogImpl private constructor( } private fun setLogs() { - if (numLog == null || denomLog == null) { - numLog = getLogOf(argument.numerator, base) - denomLog = getLogOf(argument.denominator, base) + if (numeratorLog == null || denominatorLog == null) { + numeratorLog = getLogOf(argument.numerator, base) + denominatorLog = getLogOf(argument.denominator, base) } } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/helpers.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/helpers.kt index 32dda70..5345450 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/helpers.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/log/helpers.kt @@ -10,7 +10,7 @@ import kotlin.math.log * * @param argument [BigInteger]: argument to use in calculation * @param base [Int]: base to use in calculation - * @return [BigDecimal]: the log of the number, using the current base + * @return [BigDecimal]: the log of the argument, using the specified base */ internal fun getLogOf(argument: BigInteger, base: Int): BigDecimal { val logNum = log(argument.toDouble(), base.toDouble()) diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/SqrtImpl.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/SqrtImpl.kt index d27291c..83ffb66 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/SqrtImpl.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/SqrtImpl.kt @@ -2,6 +2,7 @@ package xyz.lbres.exactnumbers.irrationals.sqrt import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.ext.divideBy +import xyz.lbres.exactnumbers.ext.isWholeNumber import xyz.lbres.exactnumbers.utils.createHashCode import xyz.lbres.exactnumbers.utils.divideByZero import java.math.BigDecimal @@ -11,8 +12,8 @@ internal class SqrtImpl(override val radicand: ExactFraction) : Sqrt() { override val type = TYPE override val isInverted = false - private var numRoot: BigDecimal? = null - private var denomRoot: BigDecimal? = null + private var numeratorRoot: BigDecimal? = null + private var denominatorRoot: BigDecimal? = null private var simplified: Pair? = null init { @@ -32,7 +33,7 @@ internal class SqrtImpl(override val radicand: ExactFraction) : Sqrt() { override fun isRational(): Boolean { setRoots() - return !numRoot!!.toPlainString().contains('.') && !denomRoot!!.toPlainString().contains('.') + return numeratorRoot!!.isWholeNumber() && denominatorRoot!!.isWholeNumber() } override fun getRationalValue(): ExactFraction? { @@ -41,30 +42,28 @@ internal class SqrtImpl(override val radicand: ExactFraction) : Sqrt() { } setRoots() - return ExactFraction(numRoot!!.toBigInteger(), denomRoot!!.toBigInteger()) + return ExactFraction(numeratorRoot!!.toBigInteger(), denominatorRoot!!.toBigInteger()) } - // uses the formula sqrt(x/y) = sqrt(x)/sqrt(y) to reduce loss of precision when casting to Double + // uses the formula sqrt(x/y) = sqrt(x)/sqrt(y) to increase precision override fun getValue(): BigDecimal { setRoots() - return numRoot!!.divideBy(denomRoot!!) + return numeratorRoot!!.divideBy(denominatorRoot!!) } override fun getSimplified(): Pair { - if (simplified == null) { - simplified = if (radicand.isZero() || radicand == ExactFraction.ONE) { - Pair(ExactFraction.ONE, this) - } else { - val numWhole = extractWholeOf(radicand.numerator) - val denomWhole = extractWholeOf(radicand.denominator) - val whole = ExactFraction(numWhole, denomWhole) - - val newNum = radicand.numerator / (numWhole * numWhole) - val newDenom = radicand.denominator / (denomWhole * denomWhole) - val newRadicand = ExactFraction(newNum, newDenom) - - Pair(whole, SqrtImpl(newRadicand)) - } + if (simplified == null && (radicand.isZero() || radicand == ExactFraction.ONE)) { + simplified = Pair(ExactFraction.ONE, this) + } else if (simplified == null) { + val numeratorWhole = extractWholeOf(radicand.numerator) + val denominatorWhole = extractWholeOf(radicand.denominator) + val whole = ExactFraction(numeratorWhole, denominatorWhole) + + val newNumerator = radicand.numerator / (numeratorWhole * numeratorWhole) + val newDenominator = radicand.denominator / (denominatorWhole * denominatorWhole) + val newRadicand = ExactFraction(newNumerator, newDenominator) + + simplified = Pair(whole, SqrtImpl(newRadicand)) } return simplified!! @@ -76,9 +75,9 @@ internal class SqrtImpl(override val radicand: ExactFraction) : Sqrt() { * Populate numRoot and denomRoot, if not already set */ private fun setRoots() { - if (numRoot == null || denomRoot == null) { - numRoot = getRootOf(radicand.numerator) - denomRoot = getRootOf(radicand.denominator) + if (numeratorRoot == null || denominatorRoot == null) { + numeratorRoot = getRootOf(radicand.numerator) + denominatorRoot = getRootOf(radicand.denominator) } } diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/castingUtils.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/castingUtils.kt index 7c81db5..a001dcd 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/castingUtils.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/castingUtils.kt @@ -9,11 +9,11 @@ import java.math.BigInteger * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Byte] value as a byte + * @param baseType [String]: type of value + * @return [Byte]: value as a byte */ -internal fun castToByte(decimal: BigDecimal, value: T, type: String): Byte { - val createException = { CastingOverflowException(type, "Byte", value.toString(), value) } +internal fun castToByte(decimal: BigDecimal, value: T, baseType: String): Byte { + val createException = { CastingOverflowException(baseType, "Byte", value.toString(), value) } return castNumber(decimal, Byte.MIN_VALUE, Byte.MAX_VALUE, BigDecimal::toByte, createException, false) } @@ -22,11 +22,11 @@ internal fun castToByte(decimal: BigDecimal, value: T, type: String): Byte { * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Char] value as a char + * @param baseType [String]: type of value + * @return [Char]: value as a char */ -internal fun castToChar(decimal: BigDecimal, value: T, type: String): Char { - val createException = { CastingOverflowException(type, "Char", value.toString(), value) } +internal fun castToChar(decimal: BigDecimal, value: T, baseType: String): Char { + val createException = { CastingOverflowException(baseType, "Char", value.toString(), value) } val minValue = Char.MIN_VALUE.code val maxValue = Char.MAX_VALUE.code @@ -39,11 +39,11 @@ internal fun castToChar(decimal: BigDecimal, value: T, type: String): Char { * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Short] value as a short + * @param baseType [String]: type of value + * @return [Short]: value as a short */ -internal fun castToShort(decimal: BigDecimal, value: T, type: String): Short { - val createException = { CastingOverflowException(type, "Short", value.toString(), value) } +internal fun castToShort(decimal: BigDecimal, value: T, baseType: String): Short { + val createException = { CastingOverflowException(baseType, "Short", value.toString(), value) } return castNumber(decimal, Short.MIN_VALUE, Short.MAX_VALUE, BigDecimal::toShort, createException, false) } @@ -52,11 +52,11 @@ internal fun castToShort(decimal: BigDecimal, value: T, type: String): Short * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Int] value as an int + * @param baseType [String]: type of value + * @return [Int]: value as an int */ -internal fun castToInt(decimal: BigDecimal, value: T, type: String): Int { - val createException = { CastingOverflowException(type, "Int", value.toString(), value) } +internal fun castToInt(decimal: BigDecimal, value: T, baseType: String): Int { + val createException = { CastingOverflowException(baseType, "Int", value.toString(), value) } return castNumber(decimal, Int.MIN_VALUE, Int.MAX_VALUE, BigDecimal::toInt, createException, false) } @@ -65,11 +65,11 @@ internal fun castToInt(decimal: BigDecimal, value: T, type: String): Int { * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Long] value as a long + * @param baseType [String]: type of value + * @return [Long]: value as a long */ -internal fun castToLong(decimal: BigDecimal, value: T, type: String): Long { - val createException = { CastingOverflowException(type, "Long", value.toString(), value) } +internal fun castToLong(decimal: BigDecimal, value: T, baseType: String): Long { + val createException = { CastingOverflowException(baseType, "Long", value.toString(), value) } return castNumber(decimal, Long.MIN_VALUE, Long.MAX_VALUE, BigDecimal::toLong, createException, false) } @@ -78,11 +78,11 @@ internal fun castToLong(decimal: BigDecimal, value: T, type: String): Long { * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Float] value as a float + * @param baseType [String]: type of value + * @return [Float]: value as a float */ -internal fun castToFloat(decimal: BigDecimal, value: T, type: String): Float { - val createException = { CastingOverflowException(type, "Float", value.toString(), value) } +internal fun castToFloat(decimal: BigDecimal, value: T, baseType: String): Float { + val createException = { CastingOverflowException(baseType, "Float", value.toString(), value) } return castNumber(decimal, -Float.MAX_VALUE, Float.MAX_VALUE, BigDecimal::toFloat, createException, true) } @@ -91,11 +91,11 @@ internal fun castToFloat(decimal: BigDecimal, value: T, type: String): Float * * @param decimal [BigDecimal]: number to cast as decimal * @param value T: number to cast - * @param type [String]: base type - * @return [Double] value as a double + * @param baseType [String]: type of value + * @return [Double]: value as a double */ -internal fun castToDouble(decimal: BigDecimal, value: T, type: String): Double { - val createException = { CastingOverflowException(type, "Double", value.toString(), value) } +internal fun castToDouble(decimal: BigDecimal, value: T, baseType: String): Double { + val createException = { CastingOverflowException(baseType, "Double", value.toString(), value) } return castNumber(decimal, -Double.MAX_VALUE, Double.MAX_VALUE, BigDecimal::toDouble, createException, true) } @@ -105,7 +105,7 @@ internal fun castToDouble(decimal: BigDecimal, value: T, type: String): Doub * @param value [BigDecimal]: number to cast * @param minValue T: minimum allowed value * @param maxValue T: maximum allowed value - * @param cast (BigDecimal) -> T: function to cast [value] + * @param cast (BigDecimal) -> T: function to perform cast * @param getOverflowException () -> [CastingOverflowException]: get exception to throw if number exceeds supported values * @param isDecimal [Boolean]: flag to indicate if [value] is being cast to a whole number or a decimal * @return T: result of cast, if succeeded diff --git a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/constants.kt b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/constants.kt index 493db94..5d1735d 100644 --- a/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/constants.kt +++ b/exact-numbers/src/main/kotlin/xyz/lbres/exactnumbers/utils/constants.kt @@ -1,7 +1,7 @@ package xyz.lbres.exactnumbers.utils /** - * Error to be thrown when dividing by zero + * Error to throw when dividing by zero */ internal val divideByZero = ArithmeticException("divide by zero") diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/stringTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/stringTests.kt index 484657d..185f579 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/stringTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/stringTests.kt @@ -105,7 +105,7 @@ fun runParseDecimalTests() { assertEquals(expected, parseDecimal(s)) s = "-5E-10" // -0.0000000005 - expected = ExactFraction(-5, 10000000000) + expected = ExactFraction(-1, 2000000000) assertEquals(expected, parseDecimal(s)) s = "-5E10" // -50000000000 @@ -193,6 +193,12 @@ fun runParseEFStringTests() { s = "EF[1]" assertFailsWithMessage("Invalid EF string format: EF[1]") { parseEFString(s) } + s = "EF[123]" + assertFailsWithMessage("Invalid EF string format: EF[123]") { parseEFString(s) } + + s = "EF[1-1]" + assertFailsWithMessage("Invalid EF string format: EF[1-1]") { parseEFString(s) } + s = "EF[1 1 1]" assertFailsWithMessage("Invalid EF string format: EF[1 1 1]") { parseEFString(s) } } @@ -284,6 +290,10 @@ fun runToDecimalStringTests() { ef = ExactFraction(bi, 3) expected = "33333333333333333333.333333" assertEquals(expected, ef.toDecimalString(6)) + + // exception + val errorMessage = "Number of digits must be non-negative" + assertFailsWithMessage(errorMessage) { createDecimalString(ExactFraction(3), -3) } } fun runToFractionStringTests() { diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/timesDivPowTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/timesDivPowTests.kt index 81f036a..70391ca 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/timesDivPowTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/timesDivPowTests.kt @@ -89,6 +89,7 @@ fun runPowTests() { runCommonPowTests(ExactFraction::pow) // other number types + runMultiTypePowTest(ExactFraction(0), 0, ExactFraction(1)) runMultiTypePowTest(ExactFraction(0), 100, ExactFraction(0)) runMultiTypePowTest(ExactFraction(12, 49), 0, ExactFraction(1)) runMultiTypePowTest(ExactFraction(3, 8), -3, ExactFraction(512, 27)) diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/unaryNonOpTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/unaryNonOpTests.kt index a530b65..137f2fd 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/unaryNonOpTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/exactfraction/unaryNonOpTests.kt @@ -141,10 +141,6 @@ fun runRoundToWholeTests() { assertEquals(expected, ef.roundToWhole()) assertEquals(expected, ef.roundToWhole()) - ef = ExactFraction(-5, 2) - expected = -ExactFraction.THREE - assertEquals(expected, ef.roundToWhole()) - ef = ExactFraction(17, 100000) expected = ExactFraction.ZERO assertEquals(expected, ef.roundToWhole()) @@ -166,12 +162,17 @@ fun runRoundToWholeTests() { expected = ExactFraction.ONE assertEquals(expected, ef.roundToWhole(RoundingMode.UP)) + ef = ExactFraction(15, 2) + expected = ExactFraction.SEVEN + assertEquals(expected, ef.roundToWhole(RoundingMode.HALF_DOWN)) + ef = ExactFraction("9.99999999999") expected = ExactFraction.NINE assertEquals(expected, ef.roundToWhole(RoundingMode.DOWN)) } fun runIsWholeNumberTests() { + // whole var ef = ExactFraction.ZERO assertTrue(ef.isWholeNumber()) @@ -181,6 +182,7 @@ fun runIsWholeNumberTests() { ef = ExactFraction(-123456789) assertTrue(ef.isWholeNumber()) + // fraction ef = ExactFraction.HALF assertFalse(ef.isWholeNumber()) diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/castingTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/castingTests.kt index f7112d7..29509d8 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/castingTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/castingTests.kt @@ -9,8 +9,6 @@ import xyz.lbres.exactnumbers.testutils.assertSucceeds import xyz.lbres.exactnumbers.testutils.getCastingOverflowAssertion import kotlin.test.assertEquals -private val one = ExactFraction.ONE - private val assertCastingOverflow = getCastingOverflowAssertion("Term") fun runToByteTests() { @@ -112,11 +110,11 @@ private fun runWholeNumberCastingTests(castLong: (Long) -> T, castT factors = listOf(Sqrt(17), Pi(), Pi(), Log(1245, 12)) term = Term.fromValues(ExactFraction(-123, 7), factors) - if (minValue.toLong() <= -2050) { + if (type == "Byte") { + assertCastingOverflow(type, term) { castTerm(term) } + } else { expected = castLong(-2050) assertEquals(expected, castTerm(term)) - } else { - assertCastingOverflow(type, term) { castTerm(term) } } term = Term.fromValues(ExactFraction(minValue.toLong()), listOf(Log(11).inverse())) diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/constuctorTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/constuctorTests.kt index 452560a..a0aed71 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/constuctorTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/constuctorTests.kt @@ -3,7 +3,6 @@ package xyz.lbres.exactnumbers.expressions.term import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.irrationals.IrrationalNumber import xyz.lbres.exactnumbers.irrationals.log.Log -import xyz.lbres.exactnumbers.irrationals.pi.Pi import xyz.lbres.exactnumbers.irrationals.sqrt.Sqrt import xyz.lbres.exactnumbers.testutils.TestNumber @@ -17,14 +16,6 @@ private val sqrtPartialWhole = Sqrt(8) private val sqrtWholeEF = Sqrt(ExactFraction(9, 25)) private val sqrtDecimal = Sqrt(11) -private val pi = Pi() -private val piInverse = Pi().inverse() - -private val testNumber1 = TestNumber(ExactFraction(5, 6)) -private val testNumber2 = TestNumber(ExactFraction.SEVEN) - -private val one = ExactFraction.ONE - fun runConstructorTests() { runFactorsConstructorTests() runComponentConstructorTests() @@ -54,8 +45,8 @@ private fun runFactorsConstructorTests() { term = Term.fromValues(ExactFraction(-17, 100043), emptyList()) checkTerm(term, ExactFraction(-17, 100043)) - term = Term.fromValues(one, listOf(logWhole, logInverse)) var factors: List> = listOf(logWhole, logInverse) + term = Term.fromValues(one, factors) checkTerm(term, one, factors) term = Term.fromValues(one, listOf(sqrtWhole)) @@ -64,16 +55,16 @@ private fun runFactorsConstructorTests() { term = Term.fromValues(one, listOf(pi)) checkTerm(term, one, listOf(pi)) - term = Term.fromValues(one, listOf(pi, piInverse)) factors = listOf(pi, piInverse) + term = Term.fromValues(one, factors) checkTerm(term, one, factors) // multi type term = Term.fromValues(ExactFraction(-17, 100043), listOf(logWhole)) checkTerm(term, ExactFraction(-17, 100043), listOf(logWhole)) - term = Term.fromValues(ExactFraction.NEG_ONE, listOf(piInverse, logWhole)) factors = listOf(piInverse, logWhole) + term = Term.fromValues(ExactFraction.NEG_ONE, factors) checkTerm(term, ExactFraction.NEG_ONE, factors) factors = listOf(logChangeBase, logInverse, logDecimal, sqrtDecimal, Sqrt.ONE) @@ -139,6 +130,6 @@ private fun runComponentConstructorTests() { term = Term.fromValues(ExactFraction(-1, 5), emptyList(), sqrts, 2) checkTerm(term, ExactFraction(-1, 5), sqrts + pis) - term = Term.fromValues(ExactFraction(-1, 5), logs, sqrts, 2) - checkTerm(term, ExactFraction(-1, 5), logs + sqrts + pis) + term = Term.fromValues(ExactFraction(-1, 5), logs, sqrts, -1) + checkTerm(term, ExactFraction(-1, 5), logs + sqrts + listOf(piInverse)) } diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/equalsToStringTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/equalsToStringTests.kt index 4f6b367..3eeffa4 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/equalsToStringTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/equalsToStringTests.kt @@ -2,20 +2,11 @@ package xyz.lbres.exactnumbers.expressions.term import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.irrationals.log.Log -import xyz.lbres.exactnumbers.irrationals.pi.Pi import xyz.lbres.exactnumbers.irrationals.sqrt.Sqrt import xyz.lbres.exactnumbers.testutils.TestNumber import kotlin.test.assertEquals import kotlin.test.assertNotEquals -private val log1 = Log(ExactFraction(15, 4)) -private val log2 = Log(8, 7) -private val log3 = Log(ExactFraction(19, 33)).inverse() -private val log4 = Log(ExactFraction(25, 121)) -private val testNumber1 = TestNumber(ExactFraction(5, 6)) -private val testNumber2 = TestNumber(ExactFraction.SEVEN) -private val one = ExactFraction.ONE - fun runEqualsTests() { // equal var term1 = Term.ZERO @@ -27,16 +18,13 @@ fun runEqualsTests() { term1 = Term.fromValues(one, listOf(log1, log2)) assertEquals(term1, term1) - term1 = Term.fromValues(one, listOf(Pi(), Pi())) - assertEquals(term1, term1) - - term1 = Term.fromValues(ExactFraction.EIGHT, listOf(log4, log3, log1, Sqrt(15), Pi().inverse(), Pi())) + term1 = Term.fromValues(ExactFraction.EIGHT, listOf(log4, log3, log1, Sqrt(15), piInverse, pi)) assertEquals(term1, term1) - term1 = Term.fromValues(one, listOf(Pi(), TestNumber(ExactFraction(5)))) + term1 = Term.fromValues(one, listOf(pi, TestNumber(ExactFraction(5)))) assertEquals(term1, term1) - term1 = Term.fromValues(ExactFraction.EIGHT, listOf(log4, log3, log1, Sqrt(5), Sqrt(7), Pi().inverse(), Pi())) + term1 = Term.fromValues(ExactFraction.EIGHT, listOf(log4, log3, log1, Sqrt(5), Sqrt(7), piInverse, pi)) var term2 = Term.fromValues(ExactFraction.EIGHT, listOf(log4, log3, log1, Sqrt(35))) assertEquals(term1, term2) assertEquals(term2, term1) @@ -46,13 +34,13 @@ fun runEqualsTests() { assertEquals(term1, term2) assertEquals(term2, term1) - term1 = Term.fromValues(ExactFraction(-4, 7), listOf(testNumber2, Sqrt(ExactFraction(7, 9)), Pi(), log1, log1.inverse())) - term2 = Term.fromValues(ExactFraction(-4, 3), listOf(Sqrt(7), Pi())) + term1 = Term.fromValues(ExactFraction(-4, 7), listOf(testNumber2, Sqrt(ExactFraction(7, 9)), pi, log1, log1.inverse())) + term2 = Term.fromValues(ExactFraction(-4, 3), listOf(Sqrt(7), pi)) assertEquals(term1, term2) assertEquals(term2, term1) - term1 = Term.fromValues(ExactFraction(-4, 7), listOf(testNumber2, Sqrt(ExactFraction(7, 9)), Pi(), log1, log1.inverse())) - term2 = Term.fromValues(ExactFraction(-4, 3), listOf(Sqrt(7), Sqrt.ONE, Pi().inverse(), Pi(), Pi())) + term1 = Term.fromValues(ExactFraction(-4, 7), listOf(testNumber2, Sqrt(ExactFraction(7, 9)), pi, log1, log1.inverse())) + term2 = Term.fromValues(ExactFraction(-4, 3), listOf(Sqrt(7), Sqrt.ONE, piInverse, pi, pi)) assertEquals(term1, term2) assertEquals(term2, term1) @@ -72,38 +60,23 @@ fun runEqualsTests() { assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(one, listOf(log1)) - term2 = Term.fromValues(one, listOf(log1.inverse())) - assertNotEquals(term1, term2) - assertNotEquals(term2, term1) - term1 = Term.fromValues(one, listOf(log1)) term2 = Term.fromValues(one, listOf(log1, log2)) assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(one, listOf(Pi())) + term1 = Term.fromValues(one, listOf(pi)) term2 = Term.ONE assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(one, listOf(Pi())) - term2 = Term.fromValues(one, listOf(Pi().inverse())) + term1 = Term.fromValues(one, listOf(pi)) + term2 = Term.fromValues(one, listOf(piInverse)) assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(one, listOf(Pi(), Pi().inverse())) - term2 = Term.fromValues(one, listOf(Pi().inverse())) - assertNotEquals(term1, term2) - assertNotEquals(term2, term1) - - term1 = Term.fromValues(one, listOf(Sqrt(12))) - term2 = Term.ONE - assertNotEquals(term1, term2) - assertNotEquals(term2, term1) - - term1 = Term.fromValues(one, listOf(Sqrt(12))) - term2 = Term.fromValues(one, listOf(Sqrt(ExactFraction(1, 12)))) + term1 = Term.fromValues(one, listOf(pi, piInverse)) + term2 = Term.fromValues(one, listOf(piInverse)) assertNotEquals(term1, term2) assertNotEquals(term2, term1) @@ -117,18 +90,18 @@ fun runEqualsTests() { assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(ExactFraction(5, 7), listOf(log1, log1, Pi(), Pi().inverse())) - term2 = Term.fromValues(ExactFraction.FIVE, listOf(log1, log1, Pi(), Pi().inverse())) + term1 = Term.fromValues(ExactFraction(5, 7), listOf(log1, log1, pi, piInverse)) + term2 = Term.fromValues(ExactFraction.FIVE, listOf(log1, log1, pi, piInverse)) assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(ExactFraction.EIGHT, listOf(log3, log4, Pi().inverse())) + term1 = Term.fromValues(ExactFraction.EIGHT, listOf(log3, log4, piInverse)) term2 = Term.fromValues(ExactFraction(-17, 15), listOf(log1, log2, log3)) assertNotEquals(term1, term2) assertNotEquals(term2, term1) - term1 = Term.fromValues(ExactFraction.FOUR, listOf(Pi(), testNumber1)) - term2 = Term.fromValues(ExactFraction.FOUR, listOf(Pi(), testNumber1.inverse())) + term1 = Term.fromValues(ExactFraction.FOUR, listOf(pi, testNumber1)) + term2 = Term.fromValues(ExactFraction.FOUR, listOf(pi, testNumber1.inverse())) assertNotEquals(term1, term2) assertNotEquals(term2, term1) } @@ -158,12 +131,12 @@ fun runToStringTests() { assertEquals(expected, term.toString()) // just pi - term = Term.fromValues(one, listOf(Pi())) - expected = "<1x${Pi()}>" + term = Term.fromValues(one, listOf(pi)) + expected = "<1x$pi>" assertEquals(expected, term.toString()) - term = Term.fromValues(one, listOf(Pi(), Pi().inverse(), Pi())) - expected = "<1x${Pi()}x${Pi().inverse()}x${Pi()}>" + term = Term.fromValues(one, listOf(pi, piInverse, pi)) + expected = "<1x${pi}x${piInverse}x$pi>" assertEquals(expected, term.toString()) // just sqrt @@ -176,16 +149,16 @@ fun runToStringTests() { assertEquals(expected, term.toString()) // mix - term = Term.fromValues(ExactFraction.EIGHT, listOf(log3, Sqrt(12), testNumber2, Pi())) - expected = "<8x${log3}x${Sqrt(12)}x${testNumber2}x${Pi()}>" + term = Term.fromValues(ExactFraction.EIGHT, listOf(log3, Sqrt(12), testNumber2, pi)) + expected = "<8x${log3}x${Sqrt(12)}x${testNumber2}x$pi>" assertEquals(expected, term.toString()) val sqrt1 = Sqrt(ExactFraction(1000, 109)) val sqrt2 = Sqrt(5096) term = Term.fromValues( ExactFraction(-100, 333), - listOf(log2, log2, log4, testNumber1, log1, sqrt1, sqrt2, Pi().inverse(), Pi()) + listOf(log2, log2, log4, testNumber1, log1, sqrt1, sqrt2, piInverse, pi) ) - expected = "<[-100/333]x${log2}x${log2}x${log4}x${testNumber1}x${log1}x${sqrt1}x${sqrt2}x${Pi().inverse()}x${Pi()}>" + expected = "<[-100/333]x${log2}x${log2}x${log4}x${testNumber1}x${log1}x${sqrt1}x${sqrt2}x${piInverse}x$pi>" assertEquals(expected, term.toString()) } diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/getComponentsTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/getComponentsTests.kt index 7a50b3c..3f414a9 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/getComponentsTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/getComponentsTests.kt @@ -9,16 +9,8 @@ import xyz.lbres.exactnumbers.testutils.TestNumber import xyz.lbres.kotlinutils.list.StringList import kotlin.test.assertEquals -private val log1 = Log(ExactFraction(15, 4)) -private val log2 = Log(8, 7) -private val log3 = Log(ExactFraction(19, 33)).inverse() -private val log4 = Log(ExactFraction(25, 121)) -private val testNumber1 = TestNumber(ExactFraction(3, 4)) -private val testNumber2 = TestNumber(ExactFraction.SEVEN) -private val one = ExactFraction.ONE - fun runGetFactorsByTypeTests() { - val types = listOf(Log.TYPE, Pi.TYPE, Sqrt.TYPE, TestNumber.TYPE) + val types = listOf(Log.TYPE, Pi.TYPE, Sqrt.TYPE, "Test") // zero var term = Term.fromValues(ExactFraction.ZERO, emptyList()) @@ -27,6 +19,9 @@ fun runGetFactorsByTypeTests() { term = Term.fromValues(one, listOf(log1, log2, testNumber1, Pi(), TestNumber(ExactFraction.ZERO))) runSingleIrrationalsByTypeTest(term, types, emptyMap()) + term = Term.fromValues(one, listOf(log1, Sqrt.ZERO, testNumber1, Pi())) + runSingleIrrationalsByTypeTest(term, types, emptyMap()) + // non-zero term = Term.fromValues(ExactFraction(4, 7), emptyList()) runSingleIrrationalsByTypeTest(term, types, emptyMap()) @@ -44,7 +39,7 @@ fun runGetFactorsByTypeTests() { runSingleIrrationalsByTypeTest( term, types + listOf("Random"), mapOf( - TestNumber.TYPE to listOf(testNumber1, testNumber2.inverse()), + "Test" to listOf(testNumber1, testNumber2.inverse()), Log.TYPE to listOf(log2), Pi.TYPE to listOf(Pi().inverse()) ) @@ -105,51 +100,43 @@ fun runGetLogsTests() { @Suppress("Deprecation") fun runGetPiCountTests() { // zero - var expected = 0 - var term = Term.fromValues(one, emptyList()) - assertEquals(expected, term.getPiCount()) + assertEquals(0, term.getPiCount()) term = Term.fromValues(ExactFraction.TEN, emptyList()) - assertEquals(expected, term.getPiCount()) + assertEquals(0, term.getPiCount()) term = Term.fromValues(one, listOf(Pi(), Pi().inverse())) - assertEquals(expected, term.getPiCount()) + assertEquals(0, term.getPiCount()) term = Term.fromValues(one, listOf(Pi(), Pi().inverse(), Pi(), Pi().inverse(), Pi(), Pi().inverse())) - assertEquals(expected, term.getPiCount()) + assertEquals(0, term.getPiCount()) term = Term.fromValues(one, listOf(log1, log2, Sqrt(ExactFraction(64, 9)))) - assertEquals(expected, term.getPiCount()) + assertEquals(0, term.getPiCount()) term = Term.fromValues(one, listOf(log3, log4, log2, Pi().inverse(), Pi(), Pi().inverse(), Pi())) - assertEquals(expected, term.getPiCount()) + assertEquals(0, term.getPiCount()) // just pi term = Term.fromValues(one, listOf(Pi())) - expected = 1 - assertEquals(expected, term.getPiCount()) + assertEquals(1, term.getPiCount()) term = Term.fromValues(one, listOf(Pi().inverse())) - expected = -1 - assertEquals(expected, term.getPiCount()) + assertEquals(-1, term.getPiCount()) term = Term.fromValues(one, listOf(Pi().inverse(), Pi().inverse(), Pi().inverse())) - expected = -3 - assertEquals(expected, term.getPiCount()) + assertEquals(-3, term.getPiCount()) term = Term.fromValues(one, listOf(Pi(), Pi().inverse(), Pi(), Pi(), Pi().inverse())) - expected = 1 - assertEquals(expected, term.getPiCount()) + assertEquals(1, term.getPiCount()) // mix term = Term.fromValues(one, listOf(log2, Sqrt(2), Pi().inverse())) - expected = -1 - assertEquals(expected, term.getPiCount()) + assertEquals(-1, term.getPiCount()) term = Term.fromValues(ExactFraction.EIGHT, listOf(log3, log2, Sqrt(36), Pi(), Pi(), Pi().inverse(), Pi())) - expected = 2 - assertEquals(expected, term.getPiCount()) + assertEquals(2, term.getPiCount()) } @Suppress("Deprecation") diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/simplifyGetValuesTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/simplifyGetValuesTests.kt index 91c4142..cb8f8b1 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/simplifyGetValuesTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/simplifyGetValuesTests.kt @@ -2,23 +2,12 @@ package xyz.lbres.exactnumbers.expressions.term import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.irrationals.log.Log -import xyz.lbres.exactnumbers.irrationals.pi.Pi import xyz.lbres.exactnumbers.irrationals.sqrt.Sqrt -import xyz.lbres.exactnumbers.testutils.TestNumber import java.math.BigDecimal import kotlin.test.assertEquals -private val log1 = Log(ExactFraction(15, 4)) -private val log2 = Log(8, 7) -private val sqrt = Sqrt(ExactFraction(20, 33)) -private val testNumber1 = TestNumber(ExactFraction(3, 4)) -private val testNumber2 = TestNumber(ExactFraction.SEVEN) -private val pi = Pi() -private val piInverse = Pi().inverse() -private val one = ExactFraction.ONE - fun runCommonSimplifyTests(simplify: (Term) -> Term) { - // simplified + // unsimplified var term = Term.fromValues(ExactFraction.EIGHT, listOf(pi, piInverse)) var result = simplify(term) checkTerm(result, ExactFraction.EIGHT) @@ -38,10 +27,9 @@ fun runCommonSimplifyTests(simplify: (Term) -> Term) { expectedFactors = listOf(piInverse) checkTerm(result, -ExactFraction.HALF, expectedFactors) - term = Term.fromValues(ExactFraction.TEN, listOf(Sqrt.ONE, sqrt, testNumber1, testNumber1, testNumber1.inverse(), testNumber1.inverse(), testNumber1.inverse())) + term = Term.fromValues(ExactFraction.TEN, listOf(Sqrt.ONE, Sqrt(ExactFraction(20, 33)), testNumber1, testNumber1, testNumber1.inverse(), testNumber1.inverse(), testNumber1.inverse())) result = simplify(term) expectedFactors = listOf(Sqrt(ExactFraction(5, 33)), testNumber1.inverse()) - var sqrts = listOf(Sqrt(ExactFraction(5, 33))) checkTerm(result, ExactFraction(20), expectedFactors) term = Term.fromValues(ExactFraction.TWO, listOf(Sqrt(64), Sqrt(ExactFraction(75, 98)), Sqrt(26))) @@ -54,9 +42,8 @@ fun runCommonSimplifyTests(simplify: (Term) -> Term) { listOf(log2, log2, log1, log2.inverse(), piInverse, piInverse, piInverse, pi) ) result = simplify(term) - var logs = listOf(log2, log1) - var pis = listOf(piInverse, piInverse) - checkTerm(result, ExactFraction(18, 5), logs + pis) + expectedFactors = listOf(log2, log1, piInverse, piInverse) + checkTerm(result, ExactFraction(18, 5), expectedFactors) term = Term.fromValues(ExactFraction.FOUR, listOf(Log(100), Sqrt(9), testNumber1, Sqrt(ExactFraction(1, 4)))) result = simplify(term) @@ -65,13 +52,8 @@ fun runCommonSimplifyTests(simplify: (Term) -> Term) { term = Term.fromValues(-ExactFraction.EIGHT, listOf(Sqrt(ExactFraction(27, 98)), piInverse)) result = simplify(term) expectedFactors = listOf(Sqrt(ExactFraction(3, 2)), piInverse) - sqrts = listOf(Sqrt(ExactFraction(3, 2))) checkTerm(result, ExactFraction(-24, 7), expectedFactors) - term = Term.fromValues(ExactFraction(20), listOf(Log(ExactFraction(1, 27), 3).inverse())) - result = simplify(term) - checkTerm(result, ExactFraction(-20, 3)) - term = Term.fromValues( ExactFraction(3, 5), listOf( @@ -96,7 +78,7 @@ fun runCommonSimplifyTests(simplify: (Term) -> Term) { result = simplify(term) checkTerm(result, ExactFraction(-180, 7)) - // no changes + // already simplified term = Term.fromValues(ExactFraction.EIGHT, emptyList()) result = simplify(term) checkTerm(result, ExactFraction.EIGHT) diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/testutils.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/testutils.kt index 2d20a89..efcd852 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/testutils.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/testutils.kt @@ -2,8 +2,26 @@ package xyz.lbres.exactnumbers.expressions.term import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.irrationals.IrrationalNumber +import xyz.lbres.exactnumbers.irrationals.log.Log +import xyz.lbres.exactnumbers.irrationals.pi.Pi +import xyz.lbres.exactnumbers.irrationals.sqrt.Sqrt +import xyz.lbres.exactnumbers.testutils.TestNumber import kotlin.test.assertEquals +// constants to use in tests +val log1 = Log(ExactFraction(15, 4)) +val log2 = Log(8, 7) +val log3 = Log(ExactFraction(19, 33)).inverse() +val log4 = Log(ExactFraction(25, 121)) +val sqrt1 = Sqrt(99) +val sqrt2 = Sqrt(ExactFraction(64, 121)) +val sqrt3 = Sqrt(ExactFraction(15, 44)) +val pi = Pi() +val piInverse = Pi().inverse() +val testNumber1 = TestNumber(ExactFraction(3, 4)) +val testNumber2 = TestNumber(ExactFraction.SEVEN) +val one = ExactFraction.ONE + /** * Check the values in a single term * diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/timesDivTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/timesDivTests.kt index a241ab7..9bdecde 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/timesDivTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/timesDivTests.kt @@ -1,26 +1,10 @@ package xyz.lbres.exactnumbers.expressions.term import xyz.lbres.exactnumbers.exactfraction.ExactFraction -import xyz.lbres.exactnumbers.irrationals.log.Log -import xyz.lbres.exactnumbers.irrationals.pi.Pi import xyz.lbres.exactnumbers.irrationals.sqrt.Sqrt -import xyz.lbres.exactnumbers.testutils.TestNumber import xyz.lbres.exactnumbers.testutils.assertDivByZero import kotlin.test.assertEquals -private val log1 = Log(ExactFraction(15, 4)) -private val log2 = Log(8) -private val log3 = Log(ExactFraction(19, 33)) -private val log4 = Log(ExactFraction(25, 121)) -private val sqrt1 = Sqrt(99) -private val sqrt2 = Sqrt(ExactFraction(64, 121)) -private val sqrt3 = Sqrt(ExactFraction(15, 44)) -private val pi = Pi() -private val piInverse = Pi().inverse() -private val testNumber1 = TestNumber(ExactFraction(5, 6)) -private val testNumber2 = TestNumber(ExactFraction.SEVEN) -private val one = ExactFraction.ONE - fun runTimesTests() { // zero var term1 = Term.ZERO @@ -58,12 +42,6 @@ fun runTimesTests() { assertEquals(expected, term1 * term2) assertEquals(expected, term2 * term1) - term1 = Term.fromValues(one, listOf(pi, pi)) - term2 = Term.fromValues(one, listOf(piInverse)) - expected = Term.fromValues(one, listOf(pi, pi, piInverse)) - assertEquals(expected, term1 * term2) - assertEquals(expected, term2 * term1) - term1 = Term.fromValues(one, listOf(pi, piInverse, pi)) term2 = Term.fromValues(one, listOf(piInverse, pi)) expected = Term.fromValues(one, listOf(pi, pi, pi, piInverse, piInverse)) @@ -83,20 +61,8 @@ fun runTimesTests() { assertEquals(expected, term1 * term2) assertEquals(expected, term2 * term1) - term1 = Term.fromValues(one, listOf(sqrt1, sqrt3.inverse())) - term2 = Term.fromValues(one, listOf(sqrt3, sqrt2)) - expected = Term.fromValues(one, listOf(sqrt1, sqrt2, sqrt3, sqrt3.inverse())) - assertEquals(expected, term1 * term2) - assertEquals(expected, term2 * term1) - // just exact fraction term1 = Term.ONE - term2 = Term.fromValues(ExactFraction.TWO, emptyList()) - expected = Term.fromValues(ExactFraction.TWO, emptyList()) - assertEquals(expected, term1 * term2) - assertEquals(expected, term2 * term1) - - term1 = Term.fromValues(one, emptyList()) term2 = Term.fromValues(ExactFraction(-17, 3), emptyList()) expected = Term.fromValues(ExactFraction(-17, 3), emptyList()) assertEquals(expected, term1 * term2) @@ -110,9 +76,9 @@ fun runTimesTests() { // combination term1 = Term.fromValues(ExactFraction(1, 4), listOf(log1, sqrt1, testNumber1, testNumber1, pi)) - term2 = Term.fromValues(ExactFraction(-1, 3), listOf(piInverse, testNumber1.inverse(), pi)) + term2 = Term.fromValues(ExactFraction(1, 3), listOf(piInverse, testNumber1.inverse(), pi)) expected = Term.fromValues( - ExactFraction(-1, 12), + ExactFraction(1, 12), listOf(log1, sqrt1, pi, pi, piInverse, testNumber1, testNumber1, testNumber1.inverse()) ) assertEquals(expected, term1 * term2) @@ -148,10 +114,8 @@ fun runDivTests() { expected = Term.fromValues(one, listOf(log1, log2, log3)) assertEquals(expected, term1 / term2) - term1 = Term.ONE - term2 = Term.fromValues(one, listOf(log1, log2, log3)) expected = Term.fromValues(one, listOf(log1.inverse(), log2.inverse(), log3.inverse())) - assertEquals(expected, term1 / term2) + assertEquals(expected, term2 / term1) term1 = Term.fromValues(one, listOf(log1, log3)) term2 = Term.fromValues(one, listOf(log3)) @@ -164,10 +128,8 @@ fun runDivTests() { expected = Term.fromValues(one, listOf(pi)) assertEquals(expected, term1 / term2) - term1 = Term.ONE - term2 = Term.fromValues(one, listOf(pi)) expected = Term.fromValues(one, listOf(piInverse)) - assertEquals(expected, term1 / term2) + assertEquals(expected, term2 / term1) term1 = Term.fromValues(one, listOf(pi, pi, piInverse)) term2 = Term.fromValues(one, listOf(piInverse, pi, piInverse)) @@ -180,10 +142,8 @@ fun runDivTests() { expected = Term.fromValues(one, listOf(sqrt1, sqrt2, sqrt3)) assertEquals(expected, term1 / term2) - term1 = Term.ONE - term2 = Term.fromValues(one, listOf(sqrt1, sqrt2, sqrt3)) expected = Term.fromValues(one, listOf(sqrt1.inverse(), sqrt2.inverse(), sqrt3.inverse())) - assertEquals(expected, term1 / term2) + assertEquals(expected, term2 / term1) term1 = Term.fromValues(one, listOf(sqrt1, sqrt2)) term2 = Term.fromValues(one, listOf(sqrt3)) @@ -196,10 +156,8 @@ fun runDivTests() { expected = Term.fromValues(ExactFraction(-4, 3), emptyList()) assertEquals(expected, term1 / term2) - term1 = Term.ONE - term2 = Term.fromValues(ExactFraction.TWO, emptyList()) - expected = Term.fromValues(ExactFraction.HALF, emptyList()) - assertEquals(expected, term1 / term2) + expected = Term.fromValues(ExactFraction(-3, 4), emptyList()) + assertEquals(expected, term2 / term1) term1 = Term.fromValues(ExactFraction(-5, 2), emptyList()) term2 = Term.fromValues(ExactFraction(3, 4), emptyList()) diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/unaryTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/unaryTests.kt index 53a588f..b71de26 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/unaryTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/expressions/term/unaryTests.kt @@ -4,18 +4,10 @@ import xyz.lbres.exactnumbers.exactfraction.ExactFraction import xyz.lbres.exactnumbers.irrationals.log.Log import xyz.lbres.exactnumbers.irrationals.pi.Pi import xyz.lbres.exactnumbers.irrationals.sqrt.Sqrt -import xyz.lbres.exactnumbers.testutils.TestNumber import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue -private val log2 = Log(8, 7) -private val log3 = Log(ExactFraction(19, 33)).inverse() -private val log4 = Log(ExactFraction(25, 121)) -private val testNumber1 = TestNumber(ExactFraction(5, 6)) -private val testNumber2 = TestNumber(ExactFraction.SEVEN) -private val one = ExactFraction.ONE - fun runUnaryMinusTests() { var term = Term.ZERO var expected = Term.ZERO @@ -37,8 +29,8 @@ fun runUnaryMinusTests() { expected = Term.fromValues(ExactFraction.SIX, listOf(log3, log4, Sqrt(36), Pi().inverse(), testNumber2)) assertEquals(expected, -term) - term = Term.fromValues(ExactFraction(15, 44), emptyList()) - expected = Term.fromValues(ExactFraction(-15, 44), emptyList()) + term = Term.fromValues(ExactFraction(44, 15), emptyList()) + expected = Term.fromValues(ExactFraction(-44, 15), emptyList()) assertEquals(expected, -term) val factors = listOf(log2, log3, log4, Sqrt(ExactFraction(3, 5)), Sqrt(961), Pi(), Pi().inverse(), Pi()) @@ -63,7 +55,7 @@ fun runUnaryPlusTests() { term = Term.fromValues(-ExactFraction.SIX, listOf(log3, log4, Sqrt(121), Pi().inverse(), testNumber2)) assertEquals(term, +term) - term = Term.fromValues(ExactFraction(15, 44), emptyList()) + term = Term.fromValues(ExactFraction(44, 15), emptyList()) assertEquals(term, +term) term = Term.fromValues( @@ -97,9 +89,8 @@ fun runIsZeroTests() { term = Term.fromValues(-ExactFraction.HALF, listOf(log2, log2.inverse(), testNumber1)) assertFalse(term.isZero()) - term = Term.fromValues(-ExactFraction.HALF, listOf(Sqrt(64), Sqrt(ExactFraction(1, 64)))) + term = Term.fromValues(ExactFraction(-1, 1000000), listOf(Sqrt(64), Sqrt(ExactFraction(1, 64)))) assertFalse(term.isZero()) - term = Term.fromValues(ExactFraction(-1, 1000000), listOf(Pi().inverse(), Pi().inverse(), Pi().inverse())) assertFalse(term.isZero()) } diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExtTest.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExtTest.kt index 3dbac4f..50c879b 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExtTest.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/ext/BigDecimalExtTest.kt @@ -4,6 +4,8 @@ import xyz.lbres.exactnumbers.testutils.assertDivByZero import java.math.BigDecimal import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue class BigDecimalExtTest { @Test @@ -36,7 +38,42 @@ class BigDecimalExtTest { bd1 = BigDecimal("103") bd2 = BigDecimal("14") - expected = BigDecimal("7.3571428571428571429") + expected = BigDecimal("7.3571428571428571429") // rounds up assertEquals(expected, bd1.divideBy(bd2)) } + + @Test + fun testIsWholeNumber() { + // whole number + var bd = BigDecimal.ZERO + assertTrue(bd.isWholeNumber()) + + bd = BigDecimal("100") + assertTrue(bd.isWholeNumber()) + + bd = BigDecimal("-100") + assertTrue(bd.isWholeNumber()) + + bd = BigDecimal("-1234560000000000000999") + assertTrue(bd.isWholeNumber()) + + bd = BigDecimal("123456000000000.0000") + assertTrue(bd.isWholeNumber()) + + bd = BigDecimal("7.00000000000000000000000000000") + assertTrue(bd.isWholeNumber()) + + // decimal + bd = BigDecimal("0.00000000000000000001") + assertFalse(bd.isWholeNumber()) + + bd = BigDecimal("-1.01") + assertFalse(bd.isWholeNumber()) + + bd = BigDecimal("123456000000000000099.9") + assertFalse(bd.isWholeNumber()) + + bd = BigDecimal("99999999999999999999999.9") + assertFalse(bd.isWholeNumber()) + } } diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogConstructorsTest.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogConstructorsTest.kt index 3a51c01..1bceee1 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogConstructorsTest.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/LogConstructorsTest.kt @@ -43,7 +43,7 @@ class LogConstructorsTest { assertFalse(it.isInverted) } - // just number + // just argument expectedArgument = ExactFraction.TWO expectedBase = 10 logs = listOf(Log(ExactFraction.TWO), Log(2), Log(2L), Log(BigInteger.TWO)) @@ -60,7 +60,7 @@ class LogConstructorsTest { assertEquals(expectedBase, log.base) assertFalse(log.isInverted) - // number + base + // argument + base expectedArgument = ExactFraction.TWO expectedBase = 2 logs = listOf(Log(ExactFraction.TWO, 2), Log(2, 2), Log(2L, 2), Log(BigInteger.TWO, 2)) diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/castingTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/castingTests.kt index d0cea08..550dd37 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/castingTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/log/castingTests.kt @@ -8,7 +8,7 @@ import kotlin.test.assertEquals val assertCastingOverflow = getCastingOverflowAssertion("Log") fun runToByteTests() { - runWholeNumberCastingTests(Long::toByte, Log::toByte, "Byte", Byte.MAX_VALUE) + runWholeNumberCastingTests(Long::toByte, Log::toByte, "Byte") } fun runToCharTests() { @@ -35,15 +35,15 @@ fun runToCharTests() { } fun runToShortTests() { - runWholeNumberCastingTests(Long::toShort, Log::toShort, "Short", Short.MAX_VALUE) + runWholeNumberCastingTests(Long::toShort, Log::toShort, "Short") } fun runToIntTests() { - runWholeNumberCastingTests(Long::toInt, Log::toInt, "Int", Int.MAX_VALUE) + runWholeNumberCastingTests(Long::toInt, Log::toInt, "Int") } fun runToLongTests() { - runWholeNumberCastingTests({ it }, Log::toLong, "Long", Long.MAX_VALUE) + runWholeNumberCastingTests({ it }, Log::toLong, "Long") } fun runToFloatTests() { @@ -60,9 +60,8 @@ fun runToDoubleTests() { * @param castLong (Long) -> T: cast a long value to a value of the current number type * @param castLog (Log) -> T: cast a log value to a value of the current number type * @param type [String]: name of target type - * @param maxValue T: maximum valid value for the current number type */ -private fun runWholeNumberCastingTests(castLong: (Long) -> T, castLog: (Log) -> T, type: String, maxValue: T) { +private fun runWholeNumberCastingTests(castLong: (Long) -> T, castLog: (Log) -> T, type: String) { var log = Log.ZERO assertEquals(castLong(0), castLog(log)) @@ -86,11 +85,14 @@ private fun runWholeNumberCastingTests(castLong: (Long) -> T, castL val largeValue = BigInteger.TWO.pow(Byte.MAX_VALUE + 1) log = Log(largeValue, 2) - if (maxValue.toLong() <= Byte.MAX_VALUE.toLong()) { + if (type == "Byte") { assertCastingOverflow(type, log) { castLog(log) } } else { assertEquals(castLong(128), castLog(log)) } + + log = Log(largeValue + BigInteger("4"), 19) + assertEquals(castLong(30), castLog(log)) } /** diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/castingTests.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/castingTests.kt index 8f63915..35628d6 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/castingTests.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/irrationals/sqrt/castingTests.kt @@ -98,7 +98,7 @@ fun runToFloatTests() { assertEquals(max, sqrt.toFloat().toBigDecimal()) // overflow - sqrt = Sqrt((max * max * max).toBigInteger()) + sqrt = Sqrt((max * max).toBigInteger() * BigInteger.TEN) assertCastingOverflow("Float", sqrt) { sqrt.toFloat() } } diff --git a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/testutils/TestNumber.kt b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/testutils/TestNumber.kt index 2dab9d1..75d906e 100644 --- a/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/testutils/TestNumber.kt +++ b/exact-numbers/src/test/kotlin/xyz/lbres/exactnumbers/testutils/TestNumber.kt @@ -6,10 +6,10 @@ import xyz.lbres.exactnumbers.utils.createHashCode import xyz.lbres.kotlinutils.general.simpleIf /** - * Irrational implementation to use in tests + * IrrationalNumber implementation to use in tests */ class TestNumber(val value: ExactFraction, override val isInverted: Boolean = false) : IrrationalNumber() { - override val type: String = TYPE + override val type: String = "Test" override fun isZero(): Boolean = value.isZero() override fun inverse(): TestNumber = TestNumber(value, !isInverted) @@ -27,8 +27,4 @@ class TestNumber(val value: ExactFraction, override val isInverted: Boolean = fa override fun equals(other: Any?) = other is TestNumber && value == other.value && isInverted == other.isInverted override fun hashCode(): Int = createHashCode(listOf(value, isInverted, type)) override fun toString(): String = "[${value.toFractionString()}, $isInverted]" - - companion object { - const val TYPE = "Test" - } }