This commit is contained in:
2026-04-24 01:10:40 +03:00
parent eb7ce4e978
commit 24a79c5940
31 changed files with 804 additions and 0 deletions

6
.idea/copilot.data.migration.ask.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

21
output.csv Normal file
View File

@@ -0,0 +1,21 @@
X;f(X)
-1.0;-0.5869665480423778
-0.9;-0.9352384029718002
-0.8;-1.4961760304210368
-0.7000000000000001;-2.6709130967375065
-0.6000000000000001;-7.731313457128241
-0.5000000000000001;10.536936447964717
-0.40000000000000013;3.2217613031197727
-0.30000000000000016;1.92971965792051
-0.20000000000000015;1.4064231946343844
-0.10000000000000014;1.1414743318601792
0.09999999999999987;5.6049822447303335
0.19999999999999987;0.6792599777698426
0.2999999999999999;0.06689887171282584
0.3999999999999999;-0.02176594607783879
0.4999999999999999;-0.02248614282716569
0.5999999999999999;-0.012196322980954091
0.6999999999999998;-0.0048145086174475014
0.7999999999999998;-0.0012728922251139007
0.8999999999999998;-1.3893249002483576E-4
0.9999999999999998;NaN
1 X f(X)
2 -1.0 -0.5869665480423778
3 -0.9 -0.9352384029718002
4 -0.8 -1.4961760304210368
5 -0.7000000000000001 -2.6709130967375065
6 -0.6000000000000001 -7.731313457128241
7 -0.5000000000000001 10.536936447964717
8 -0.40000000000000013 3.2217613031197727
9 -0.30000000000000016 1.92971965792051
10 -0.20000000000000015 1.4064231946343844
11 -0.10000000000000014 1.1414743318601792
12 0.09999999999999987 5.6049822447303335
13 0.19999999999999987 0.6792599777698426
14 0.2999999999999999 0.06689887171282584
15 0.3999999999999999 -0.02176594607783879
16 0.4999999999999999 -0.02248614282716569
17 0.5999999999999999 -0.012196322980954091
18 0.6999999999999998 -0.0048145086174475014
19 0.7999999999999998 -0.0012728922251139007
20 0.8999999999999998 -1.3893249002483576E-4
21 0.9999999999999998 NaN

View File

@@ -0,0 +1,62 @@
package function
import function.base.ILn
import function.base.ISin
import function.logarithmic.ILog
import function.trigonometric.ICos
import function.trigonometric.ICot
import function.trigonometric.ICsc
import function.trigonometric.ISec
import kotlin.math.pow
class FunctionSystem(
private val sinImpl: ISin,
private val lnImpl: ILn,
private val cosImpl: ICos,
private val cscImpl: ICsc,
private val secImpl: ISec,
private val cotImpl: ICot,
private val logImpl: ILog,
) {
fun compute(
x: Double,
eps: Double = 1e-10,
): Double =
if (x <= 0) {
computeTrigPart(x, eps)
} else {
computeLogPart(x, eps)
}
private fun computeTrigPart(
x: Double,
eps: Double,
): Double {
val sinX = sinImpl.sin(x, eps)
val cscX = cscImpl.csc(x, eps)
val secX = secImpl.sec(x, eps)
val cosX = cosImpl.cos(x, eps)
val cotX = cotImpl.cot(x, eps)
val numerator = (sinX + cscX).pow(2) / cscX
val denominator = secX.pow(3) + cosX.pow(2) * (sinX + cotX)
return numerator / denominator
}
private fun computeLogPart(
x: Double,
eps: Double,
): Double {
val log10X = logImpl.log(10.0, x, eps)
val log5X = logImpl.log(5.0, x, eps)
val log3X = logImpl.log(3.0, x, eps)
val log2X = logImpl.log(2.0, x, eps)
val lnX = lnImpl.ln(x, eps)
val leftPart = log10X / log5X * log10X * log10X * log3X
val rightPart = (log2X / log2X).pow(3) - (log3X * lnX + log5X - log5X)
return leftPart * rightPart
}
}

View File

@@ -0,0 +1,5 @@
package function.base
interface ILn {
fun ln(x: Double, eps: Double = 1e-10): Double
}

View File

@@ -0,0 +1,5 @@
package function.base
interface ISin {
fun sin(x: Double, eps: Double = 1e-10): Double
}

View File

@@ -0,0 +1,22 @@
package function.base
import kotlin.math.abs
class LnTaylor : ILn {
override fun ln(
x: Double,
eps: Double,
): Double {
if (x <= 0) throw IllegalArgumentException("Ln is undefined for x <= 0")
val y = (x - 1) / (x + 1)
var result = 0.0
var term = y
var k = 1
while (abs(term) >= eps) {
result += term / (2 * k - 1)
term *= y * y
k++
}
return 2 * result
}
}

View File

@@ -0,0 +1,21 @@
package function.base
import kotlin.math.PI
import kotlin.math.abs
class SinTaylor : ISin {
override fun sin(
x: Double,
eps: Double,
): Double {
var result = 0.0
var term = x
var n = 1
while (abs(term) >= eps) {
result += term
term *= -x * x / ((2 * n) * (2 * n + 1))
n++
}
return result
}
}

View File

@@ -0,0 +1,5 @@
package function.logarithmic
interface ILog {
fun log(base: Double, x: Double, eps: Double = 1e-10): Double
}

View File

@@ -0,0 +1,13 @@
package function.logarithmic
import function.base.ILn
class Log(private val lnImpl: ILn) : ILog {
override fun log(base: Double, x: Double, eps: Double): Double {
if (base <= 0 || base == 1.0) throw IllegalArgumentException("Log base must be > 0 and != 1")
if (x <= 0) throw IllegalArgumentException("Log argument must be > 0")
val lnX = lnImpl.ln(x, eps)
val lnBase = lnImpl.ln(base, eps)
return lnX / lnBase
}
}

View File

@@ -0,0 +1,10 @@
package function.stubs
import function.trigonometric.ICos
class CosStub : ICos {
override fun cos(
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,10 @@
package function.stubs
import function.trigonometric.ICot
class CotStub : ICot {
override fun cot(
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,10 @@
package function.stubs
import function.trigonometric.ICsc
class CscStub : ICsc {
override fun csc(
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,10 @@
package function.stubs
import function.base.ILn
class LnStub : ILn {
override fun ln(
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,11 @@
package function.stubs
import function.logarithmic.ILog
class LogStub : ILog {
override fun log(
base: Double,
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,10 @@
package function.stubs
import function.trigonometric.ISec
class SecStub : ISec {
override fun sec(
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,10 @@
package function.stubs
import function.base.ISin
class SinStub : ISin {
override fun sin(
x: Double,
eps: Double,
): Double = 1.0
}

View File

@@ -0,0 +1,9 @@
package function.trigonometric
import function.base.ISin
class Cos(private val sinImpl: ISin) : ICos {
override fun cos(x: Double, eps: Double): Double {
return sinImpl.sin(x + Math.PI / 2, eps)
}
}

View File

@@ -0,0 +1,20 @@
package function.trigonometric
import function.base.ISin
import kotlin.math.abs
class Cot(
private val sinImpl: ISin,
) : ICot {
private val cosImpl = Cos(sinImpl)
override fun cot(
x: Double,
eps: Double,
): Double {
val sinVal = sinImpl.sin(x, eps)
val cosVal = cosImpl.cos(x, eps)
if (abs(sinVal) < 1e-8) throw ArithmeticException("Cot is undefined for sin(x) = 0")
return cosVal / sinVal
}
}

View File

@@ -0,0 +1,17 @@
package function.trigonometric
import function.base.ISin
import kotlin.math.abs
class Csc(
private val sinImpl: ISin,
) : ICsc {
override fun csc(
x: Double,
eps: Double,
): Double {
val sinVal = sinImpl.sin(x, eps)
if (abs(sinVal) < 1e-8) throw ArithmeticException("Csc is undefined for sin(x) = 0")
return 1.0 / sinVal
}
}

View File

@@ -0,0 +1,5 @@
package function.trigonometric
interface ICos {
fun cos(x: Double, eps: Double = 1e-10): Double
}

View File

@@ -0,0 +1,19 @@
package function.trigonometric
import function.base.ISin
import kotlin.math.abs
class Sec(
sinImpl: ISin,
) : ISec {
private val cosImpl = Cos(sinImpl)
override fun sec(
x: Double,
eps: Double,
): Double {
val cosVal = cosImpl.cos(x, eps)
if (abs(cosVal) < 1e-8) throw ArithmeticException("Sec is undefined for cos(x) = 0")
return 1.0 / cosVal
}
}

View File

@@ -0,0 +1,18 @@
package util
import java.io.File
class CsvWriter {
fun writeToCsv(
filename: String,
data: List<Pair<Double, Double>>,
label: String = "Result",
) {
File(filename).printWriter().use { out ->
out.println("X;$label(X)")
for ((x, result) in data) {
out.println("$x;$result")
}
}
}
}

View File

@@ -0,0 +1,36 @@
package test
import function.base.SinTaylor
import function.trigonometric.Cos
import org.junit.jupiter.api.Test
import kotlin.math.PI
import kotlin.math.cos
import kotlin.test.assertEquals
class CosTest {
private val cosImpl = Cos(SinTaylor())
@Test
fun testCosZero() {
val eps = 1e-10
val result = cosImpl.cos(0.0, eps)
assertEquals(cos(0.0), result, eps)
}
@Test
fun testCosPi() {
val eps = 1e-10
val x = PI
val result = cosImpl.cos(x, eps)
assertEquals(cos(x), result, eps)
}
@Test
fun testCosPiOver2() {
val eps = 1e-10
val x = PI / 2
val expected = cos(x)
val result = cosImpl.cos(x, eps)
assertEquals(expected, result, eps)
}
}

View File

@@ -0,0 +1,39 @@
package test
import function.base.SinTaylor
import function.trigonometric.Cot
import org.junit.jupiter.api.Test
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
class CotTest {
private val cotImpl = Cot(SinTaylor())
@Test
fun testCot() {
val eps = 1e-10
val x = 1.0
val result = cotImpl.cot(x, eps)
assertTrue(result.isFinite())
}
@Test
fun testCotInvalid() {
val eps = 1e-10
assertFailsWith<ArithmeticException> {
cotImpl.cot(0.0, eps)
}
}
@Test
fun testCotPiOver4() {
val eps = 1e-10
val x = PI / 4
val result = cotImpl.cot(x, eps)
assertEquals(cos(x) / sin(x), result, eps * 10)
}
}

View File

@@ -0,0 +1,29 @@
package test
import function.base.SinTaylor
import function.trigonometric.Csc
import integration.eps
import org.junit.jupiter.api.Test
import kotlin.math.PI
import kotlin.math.sin
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class CscTest {
private val cscImpl = Csc(SinTaylor())
@Test
fun testCscPiOver2() {
val eps = 1e-10
val x = PI / 2
val result = cscImpl.csc(x, eps)
assertEquals(1.0 / sin(x), result, eps)
}
@Test
fun testCscInvalid() {
assertFailsWith<ArithmeticException> {
cscImpl.csc(0.0, eps)
}
}
}

View File

@@ -0,0 +1,58 @@
package test
import function.FunctionSystem
import function.base.LnTaylor
import function.base.SinTaylor
import function.logarithmic.Log
import function.trigonometric.Cos
import function.trigonometric.Cot
import function.trigonometric.Csc
import function.trigonometric.Sec
import org.junit.jupiter.api.Test
import kotlin.math.PI
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
class FunctionSystemTest {
private val funcSys =
FunctionSystem(SinTaylor(), LnTaylor(), Cos(SinTaylor()), Csc(SinTaylor()), Sec(SinTaylor()), Cot(SinTaylor()), Log(LnTaylor()))
@Test
fun testTrigPart() {
val eps = 1e-10
val x = -0.5
val result = funcSys.compute(x, eps)
assertTrue(result.isFinite())
}
@Test
fun testLogPart() {
val eps = 1e-10
val x = 2.0
val result = funcSys.compute(x, eps)
assertTrue(result.isFinite())
}
@Test
fun testBoundaryXEqualsZero() {
val eps = 1e-10
assertFailsWith<ArithmeticException> {
funcSys.compute(0.0, eps)
}
}
@Test
fun testBoundaryXEqualsOne() {
val eps = 1e-10
val result = funcSys.compute(1.0, eps)
assertTrue((result).isNaN())
}
@Test
fun testTrigInvalidPoint() {
val eps = 1e-10
assertFailsWith<ArithmeticException> {
funcSys.compute(-PI, eps)
}
}
}

47
src/test/kotlin/LnTest.kt Normal file
View File

@@ -0,0 +1,47 @@
package test
import function.base.LnTaylor
import org.junit.jupiter.api.Test
import kotlin.math.ln
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class LnTest {
private val lnTaylor = LnTaylor()
@Test
fun testLnOf1() {
val eps = 1e-10
val result = lnTaylor.ln(1.0, eps)
assertEquals(0.0, result, eps)
}
@Test
fun testLnOfE() {
val eps = 1e-10
val x = Math.E
val expected = ln(x)
val result = lnTaylor.ln(x, eps)
assertEquals(expected, result, eps)
}
@Test
fun testLnSmallPositive() {
val eps = 1e-10
val x = 2.0
val expected = ln(x)
val result = lnTaylor.ln(x, eps)
assertEquals(expected, result, eps)
}
@Test
fun testLnInvalid() {
assertFailsWith<IllegalArgumentException> {
lnTaylor.ln(0.0)
}
assertFailsWith<IllegalArgumentException> {
lnTaylor.ln(-1.0)
}
}
}

View File

@@ -0,0 +1,49 @@
package test
import function.base.LnTaylor
import function.logarithmic.Log
import org.junit.jupiter.api.Test
import kotlin.math.log
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class LogTest {
private val logImpl = Log(LnTaylor())
@Test
fun testLog10() {
val eps = 1e-10
val x = 100.0
val result = logImpl.log(10.0, x, eps)
assertEquals(log(x, 10.0), result, eps)
}
@Test
fun testLog5Of25() {
val eps = 1e-10
val x = 25.0
val result = logImpl.log(5.0, x, eps)
assertEquals(2.0, result, eps)
}
@Test
fun testLogInvalidBase() {
assertFailsWith<IllegalArgumentException> {
logImpl.log(-1.0, 1.0)
}
assertFailsWith<IllegalArgumentException> {
logImpl.log(1.0, 1.0)
}
}
@Test
fun testLogInvalidX() {
assertFailsWith<IllegalArgumentException> {
logImpl.log(10.0, 0.0)
}
assertFailsWith<IllegalArgumentException> {
logImpl.log(10.0, -1.0)
}
}
}

View File

@@ -0,0 +1,38 @@
package test
import function.base.SinTaylor
import function.trigonometric.Sec
import org.junit.jupiter.api.Test
import kotlin.math.PI
import kotlin.math.cos
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class SecTest {
private val secImpl = Sec(SinTaylor())
@Test
fun testSecOne() {
val eps = 1e-10
val x = 0.5
val expected = 1.0 / cos(x)
val result = secImpl.sec(x, eps)
assertEquals(expected, result, eps * 10)
}
@Test
fun testSecZero() {
val eps = 1e-10
val x = 0.0
val result = secImpl.sec(x, eps)
assertEquals(1.0 / cos(x), result, eps * 10)
}
@Test
fun testSecInvalid() {
val eps = 1e-10
assertFailsWith<ArithmeticException> {
secImpl.sec(PI / 2, eps)
}
}
}

View File

@@ -0,0 +1,45 @@
package test
import function.base.SinTaylor
import org.junit.jupiter.api.Test
import kotlin.math.PI
import kotlin.math.sin
import kotlin.test.assertEquals
class SinTest {
private val sinTaylor = SinTaylor()
@Test
fun testSinZero() {
val eps = 1e-10
val result = sinTaylor.sin(0.0, eps)
assertEquals(0.0, result, eps)
}
@Test
fun testSinPiOver2() {
val eps = 1e-10
val x = PI / 2
val expected = sin(x)
val result = sinTaylor.sin(x, eps)
assertEquals(expected, result, eps)
}
@Test
fun testSinSmallX() {
val eps = 1e-10
val x = 0.1
val expected = sin(x)
val result = sinTaylor.sin(x, eps)
assertEquals(expected, result, eps)
}
@Test
fun testSinNegative() {
val eps = 1e-10
val x = -0.1
val expected = sin(x)
val result = sinTaylor.sin(x, eps)
assertEquals(expected, result, eps)
}
}

View File

@@ -0,0 +1,144 @@
package integration
import function.FunctionSystem
import function.base.LnTaylor
import function.base.SinTaylor
import function.logarithmic.Log
import function.stubs.CosStub
import function.stubs.CotStub
import function.stubs.CscStub
import function.stubs.LnStub
import function.stubs.LogStub
import function.stubs.SecStub
import function.stubs.SinStub
import function.trigonometric.Cos
import function.trigonometric.Cot
import function.trigonometric.Csc
import function.trigonometric.Sec
import org.junit.jupiter.api.Test
val eps = 1e-10
class BottomUpIntegrationTest {
@Test
fun step1ReplaceLnStub() {
val sin = SinStub()
val ln = LnTaylor()
val cos = CosStub()
val csc = CscStub()
val sec = SecStub()
val cot = CotStub()
val log = LogStub()
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
funcSys.compute(0.5)
}
@Test
fun step2ReplaceSinStub() {
val sin = SinTaylor()
val ln = LnStub()
val cos = CosStub()
val csc = CscStub()
val sec = SecStub()
val cot = CotStub()
val log = LogStub()
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
}
@Test
fun step3CosWithSin() {
val sin = SinTaylor()
val ln = LnStub()
val cos = Cos(sin)
val csc = CscStub()
val sec = SecStub()
val cot = CotStub()
val log = LogStub()
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
}
@Test
fun step4CscWithSin() {
val sin = SinTaylor()
val ln = LnStub()
val cos = CosStub()
val csc = Csc(sin)
val sec = SecStub()
val cot = CotStub()
val log = LogStub()
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
}
@Test
fun step5SecWithCosSin() {
val sin = SinTaylor()
val ln = LnStub()
val cos = Cos(sin)
val csc = CscStub()
val sec = Sec(sin)
val cot = CotStub()
val log = LogStub()
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
}
@Test
fun step6CotWithSinCos() {
val sin = SinTaylor()
val ln = LnStub()
val cos = Cos(sin)
val csc = CscStub()
val sec = SecStub()
val cot = Cot(sin)
val log = LogStub()
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
}
@Test
fun step7LogWithLn() {
val sin = SinStub()
val ln = LnTaylor()
val cos = CosStub()
val csc = CscStub()
val sec = SecStub()
val cot = CotStub()
val log = Log(ln)
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(0.5)
}
@Test
fun step8FullIntegration() {
val sin = SinTaylor()
val ln = LnTaylor()
val cos = Cos(sin)
val csc = Csc(sin)
val sec = Sec(sin)
val cot = Cot(sin)
val log = Log(ln)
val funcSys = FunctionSystem(sin, ln, cos, csc, sec, cot, log)
funcSys.compute(-0.5)
funcSys.compute(0.5)
}
}