diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/StatisticsFunctionTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/StatisticsFunctionTests.kt index 1d9fb73113..5d4ce14547 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/StatisticsFunctionTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/functions/StatisticsFunctionTests.kt @@ -44,6 +44,7 @@ class StatisticsFunctionTests : DatabaseTestsBase() { private object SampleTestTable : Table("sample_table") { val number = integer("number").nullable() } + private val data: List = listOf(4, null, 5, null, 6) private val scale = 4 @@ -63,7 +64,38 @@ class StatisticsFunctionTests : DatabaseTestsBase() { } private fun calculateStandardDeviation(isPopulation: Boolean): BigDecimal { - return calculateVariance(isPopulation).sqrt(MathContext(scale, RoundingMode.HALF_EVEN)) + return calculateVariance(isPopulation).simpleSqrt() + } + + fun BigDecimal.simpleSqrt(): BigDecimal { + if (this < BigDecimal.ZERO) throw ArithmeticException("Square root of negative number") + if (this == BigDecimal.ZERO) return BigDecimal.ZERO + + val TWO = BigDecimal(2) + val EPSILON = BigDecimal(0.1).pow(scale) + + var low = BigDecimal.ZERO + var high = max(BigDecimal.ONE) + var result = (low + high).divide(TWO) + + while (true) { + val square = result.multiply(result) + val diff = square.subtract(this).abs() + if (diff < EPSILON) { + break + } + + if (result.multiply(result) < this) { + low = result + } else { + high = result + } + result = (low + high).divide(TWO) + } + + result = result.round(MathContext(scale, RoundingMode.HALF_EVEN)) + result = result.setScale(scale) + return result } private fun calculateVariance(isPopulation: Boolean): BigDecimal {