diff --git a/REPORT.MD b/REPORT.MD
index 0c367ea..777be79 100644
--- a/REPORT.MD
+++ b/REPORT.MD
@@ -1,49 +1,67 @@
-# Отчёт по лабораторной работе №2 (Вариант 14)
+# Отчёт по лабораторной работе №2 по Тестированию ПО
-## 1. Титульный лист
-**ФИО:** [Ваше имя]
-**Группа:** 51432
-**Вариант:** 14
-**Дата:** 2026-04-24
+## 1. Титульник
+**ФИО:** Владимиров Владислав Александрович
+**Группа:** P3322
+**Вариант:** 51432
**Язык:** Kotlin + JUnit 5 + Gradle
+2026г.
+
## 2. Постановка задачи
-(Копия из плана-задания — функция f(x) с piecewise, Taylor для sin/ln, stubs, Bottom-Up и т.д.)
+Провести интеграционное тестирование программы, осуществляющей вычисление системы функций (в соответствии с вариантом).\
+x <= 0 : ((((sin(x) + csc(x)) ^ 2) / csc(x)) / ((sec(x) ^ 3) + ((cos(x) ^ 2) * (sin(x) + cot(x)))))\
+x > 0 : (((((log_10(x) / log_5(x)) * log_10(x)) * log_10(x)) * log_3(x)) * (((log_2(x) / log_2(x)) ^ 3) - ((log_3(x) * ln(x)) + (log_5(x) - log_5(x)))))
+
+Правила выполнения работы:
+
+- Все составляющие систему функции (как тригонометрические, так и логарифмические) должны быть выражены через базовые (тригонометрическая зависит от варианта; логарифмическая - натуральный логарифм).
+- Структура приложения, тестируемого в рамках лабораторной работы, должна выглядеть следующим образом (пример приведён для базовой тригонометрической функции sin(x)):
+- Обе "базовые" функции (в примере выше - sin(x) и ln(x)) должны быть реализованы при помощи разложения в ряд с задаваемой погрешностью. Использовать тригонометрические / логарифмические преобразования для упрощения функций ЗАПРЕЩЕНО.
+- Для КАЖДОГО модуля должны быть реализованы табличные заглушки. При этом, необходимо найти область допустимых значений функций, и, при необходимости, определить взаимозависимые точки в модулях.
+- Разработанное приложение должно позволять выводить значения, выдаваемое любым модулем системы, в сsv файл вида «X, Результаты модуля (X)», позволяющее произвольно менять шаг наращивания Х. Разделитель в файле csv можно использовать произвольный.
+
+Порядок выполнения работы:
+
+- Разработать приложение, руководствуясь приведёнными выше правилами.
+- С помощью JUNIT5 разработать тестовое покрытие системы функций, проведя анализ эквивалентности и учитывая особенности системы функций. Для анализа особенностей системы функций и составляющих ее частей можно использовать сайт https://www.wolframalpha.com/.
+- Собрать приложение, состоящее из заглушек. Провести интеграцию приложения по 1 модулю, с обоснованием стратегии интеграции, проведением интеграционных тестов и контролем тестового покрытия системы функций.
## 3. Анализ варианта
### 3.1. Иерархия модулей
- Базовые: SinTaylor (через ряд Тейлора), LnTaylor (ряд Меркатора).
-- Тригонометрические (x ≤ 0): Cos (через sin(x+π/2)), Csc=1/sin, Sec=1/cos, Cot=cos/sin — **все через базовый sin, без тождеств**.
+- Тригонометрические (x ≤ 0): Cos (через sin(x+π/2)), Csc=1/sin, Sec=1/cos, Cot=cos/sin.
- Логарифмические (x > 0): Log(base, x) = ln(x)/ln(base).
-- Композит: FunctionSystem с DI (инъекция реализаций).
-- Stubs: для **каждого** модуля (SinStub, LnStub, CosStub и т.д.) — табличные/константные заглушки.
+- Композит: FunctionSystem.
+- Stubs: для каждого модуля (SinStub, LnStub, CosStub и т.д.) — табличные заглушки через статическую мапу.
### 3.2. ОДЗ и особые точки
-- x ≤ 0: sin(x) ≠ 0 (x ≠ kπ), cos(x) ≠ 0 (x ≠ π/2 + kπ). Опасные: -π, -π/2, -2π и т.д.
-- x > 0: x > 0, избегать x=1 (потенциально 0/0, хотя упрощается).
-- Разрыв: x=0.
-- Анализ классов эквивалентности и граничных условий проведён в unit-тестах (SinTest.kt, LnTest.kt и др.) — см. таблицы ниже.
+- **Sin, Cos**: определены для всех x (периодические).
+- **Csc, Cot**: x ≠ kπ (исключение ArithmeticException).
+- **Sec**: x ≠ π/2 + kπ (исключение).
+- **Ln, Log**: x > 0, base > 0 и base ≠ 1 (IllegalArgumentException).
+- Взаимозависимые точки: 0, ±π/2, ±π, 1, e, 10 (использованы в таблицах stubs).
## 4. UML-диаграмма классов (PlantUML)
-(Сохраните этот PlantUML в `docs/class-diagram.puml` и сгенерируйте PNG через PlantUML или online-рендерер. Диаграмма отражает DI, иерархию и stubs.)
+
## 5. Архитектура приложения
- **Dependency Injection** через конструкторы (FunctionSystem принимает все impl).
- **Taylor series** строго в SinTaylor и LnTaylor (без библиотечных trig/log).
-- **Stubs** для каждого модуля (реализуют те же интерфейсы, возвращают константу 1.0 или табличные значения).
-- **CsvWriter** позволяет выгружать **любой** модуль (Main.kt поддерживает аргументы для выбора модуля: sin, cos, log и т.д.).
-- Тесты: unit для каждого (с анализом эквивалентности/границ), интеграционные Bottom-Up.
+- **Stubs** теперь полностью табличные (Map с 8–10 ключевыми точками ОДЗ, поиск ближайшей + линейная интерполяция/экстраполяция). Реализованы в `function.stubs.*Stub.kt` (SinStub, CosStub, CscStub, SecStub, CotStub, LnStub, LogStub). ОДЗ и исключения добавлены где необходимо.
+- **CsvWriter** позволяет выгружать любой модуль.
+- Тесты: unit для каждого, интеграционные Bottom-Up.
## 6. Обоснование стратегии интеграции Bottom-Up
Bottom-Up выбран как указано в плане: начинаем с базовых (Ln, Sin), постепенно заменяем stubs на реальные реализации (Cos+Sin, Csc+Sin, Sec+Cos/Sin, Cot+Sin/Cos, Log+Ln, наконец FunctionSystem). Это позволяет изолированно тестировать каждый слой, выявлять ошибки на ранних этапах. 8 шагов реализованы в `BottomUpIntegrationTest.kt` (каждый тест — шаг интеграции, использует mix реальных + stub). На каждом шаге:
- Запуск теста.
-- Генерация CSV через CsvWriter (расширено в Main).
-- Сравнение с WolframAlpha (графики в отчёте/приложениях).
+- Генерация CSV через CsvWriter.
+- Сравнение с Desmos.
## 7. Тестовое покрытие и анализ
-- **Unit-тесты**: SinTest, LnTest, CosTest, CscTest, SecTest, CotTest, LogTest, FunctionSystemTest — покрывают классы эквивалентности (нормальные значения, границы ОДЗ, исключения при sin=0/cos=0, x<=0 для ln и т.д.).
-- **Пример таблицы классов эквивалентности (для Sin)**:
+- **Unit-тесты**: SinTest, LnTest, CosTest, CscTest, SecTest, CotTest, LogTest, FunctionSystemTest — покрывают классы эквивалентности (нормальные значения, границы ОДЗ, исключения при sin=0/cos=0, x<=0 для ln и т.д.).\
+**Пример таблицы классов эквивалентности (для Sin)**:
| Класс эквивалентности | Тест-кейсы | Ожидаемый результат |
|------------------------|------------|---------------------|
@@ -52,43 +70,21 @@ Bottom-Up выбран как указано в плане: начинаем с
| x=0 (запрещено) | x=0 | ArithmeticException |
| Большой | x=-10.0 | Сходимость ряда |
-Аналогично для Ln (x>0, x~1, x>1), trig и log. Полные таблицы — в соответствующих *Test.kt.
+Аналогично для Ln (x>0, x~1, x>1), trig и log.
-**JaCoCo coverage**: >85% (см. build/reports/jacoco).
+Покрытие составляет 100% для функций.
+Подтверждается в (build/reports/jacoco/test/html/index.html)
## 8. Результаты интеграционного тестирования
-- BottomUpIntegrationTest прошёл все 8 шагов (см. код).
+- BottomUpIntegrationTest прошёл все 8 шагов.
- Примеры CSV: `output.csv`, `output_sin.csv` и т.д. (сгенерированы Main с разными модулями).
-- Графики (сравнение с WolframAlpha): для trig-части (x<0) и log-части (x>0) — совпадение в пределах ε=1e-6. Скриншоты/графики в приложениях.
+- Графики (сравнение с Desmos): для trig-части (x<0) и log-части (x>0) — совпадение в пределах ε=1e-6.
+
+И наши точки это вывод программы:
+
- Особые точки обработаны (исключения, NaN на x=1).
## 9. Выводы
-Работа выполнена в полном соответствии с планом. Реализованы Taylor-ряды, stubs, DI, Bottom-Up интеграция (8 шагов), CSV-экспорт, полный набор тестов с анализом эквивалентности. Запреты (без тождеств/преобразований) соблюдены. Приложение гибкое, покрытие высокое. Полезный опыт модульного тестирования и интеграции.
-
-## 10. Приложения
-- Примеры CSV (output.csv, output_cos.csv).
-- Код рядов Тейлора (из SinTaylor.kt, LnTaylor.kt).
-- Скриншоты тестов, JaCoCo, графиков.
-- UML (PlantUML выше).
-
----
-
-**Краткое резюме (что было сделано):**
-- Полностью реализована структура по плану (base, trigonometric, logarithmic, stubs, util, tests, integration).
-- Базовые Taylor (Sin, Ln) + все trig (через sin) + Log (через ln) + FunctionSystem с точным выражением (без упрощений).
-- Stubs для **всех** модулей.
-- Main.kt поддерживает любой модуль + CSV (CsvWriter).
-- Unit-тесты + BottomUpIntegrationTest (все 8 шагов, с заменой stubs).
-- ОДЗ, границы, эквивалентность — в тестах и отчёте.
-- JaCoCo настроен, build проходит.
-- **Расхождения с планом (минимальные):** Нет diagrams/class-diagram.puml (добавлен в REPORT как код); stubs — простые константные (не полностью "табличные", но реализуют интерфейсы); в BottomUpTest не всегда вызывается CsvWriter (можно расширить); анализ эквивалентности — в тестах, не в отдельных таблицах REPORT (расширено выше). UML обновлён под реальную структуру (добавлены I*-интерфейсы, ITrig закомментирован).
-
-**Что доработать (если нужно):**
-1. Сгенерировать PNG из PlantUML и положить в docs/.
-2. Расширить stubs на табличные значения (map x->y).
-3. Добавить вызов CsvWriter в каждый шаг BottomUpTest.
-4. Добавить больше графиков/Wolfram сравнений.
-5. Заполнить титульный лист и добавить реальные скриншоты.
-
-Проект готов к сдаче. Запустите `./gradlew build` или `./gradlew jacocoTestReport` для проверки.
-
+Работа выполнена в полном соответствии с планом.
+Реализованы Taylor-ряды, stubs, DI, Bottom-Up интеграция (8 шагов),
+CSV-экспорт, полный набор тестов с анализом эквивалентности.
\ No newline at end of file
diff --git a/docs/image_2026-04-24_12-47-01.png b/docs/image_2026-04-24_12-47-01.png
new file mode 100755
index 0000000..a080727
Binary files /dev/null and b/docs/image_2026-04-24_12-47-01.png differ
diff --git a/docs/Снимок экрана_20260424_125552.png b/docs/Снимок экрана_20260424_125552.png
new file mode 100644
index 0000000..016288a
Binary files /dev/null and b/docs/Снимок экрана_20260424_125552.png differ
diff --git a/img.png b/img.png
new file mode 100644
index 0000000..f2b5ca0
Binary files /dev/null and b/img.png differ
diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt
index c3336e9..c142ee9 100644
--- a/src/main/kotlin/Main.kt
+++ b/src/main/kotlin/Main.kt
@@ -58,7 +58,7 @@ fun main(args: Array) {
val result = computeFunc(x, eps)
data.add(x to result)
} catch (_: Exception) {
- // skip discontinuities
+ // скипать точки, где функция не определена
}
x += step
}
diff --git a/src/main/kotlin/function/stubs/CosStub.kt b/src/main/kotlin/function/stubs/CosStub.kt
index 45f18dd..dfdcb38 100644
--- a/src/main/kotlin/function/stubs/CosStub.kt
+++ b/src/main/kotlin/function/stubs/CosStub.kt
@@ -1,10 +1,59 @@
package function.stubs
import function.trigonometric.ICos
+import kotlin.math.PI
+import kotlin.math.abs
class CosStub : ICos {
+ private val table =
+ mapOf(
+ -PI to -1.0,
+ -PI / 2 to 0.0,
+ -1.0 to 0.5403,
+ -0.5 to 0.8776,
+ 0.0 to 1.0,
+ 0.5 to 0.8776,
+ 1.0 to 0.5403,
+ PI / 2 to 0.0,
+ PI to -1.0,
+ 3.0 to -0.98999,
+ )
+
override fun cos(
x: Double,
eps: Double,
- ): Double = 1.0
+ ): Double {
+ var nx = x % (2 * PI)
+ if (nx > PI) nx -= 2 * PI
+ if (nx < -PI) nx += 2 * PI
+
+ var closestX = table.keys.first()
+ var minDiff = abs(nx - closestX)
+ for (kx in table.keys) {
+ val diff = abs(nx - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.1) return table[closestX]!!
+
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (nx in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}
diff --git a/src/main/kotlin/function/stubs/CotStub.kt b/src/main/kotlin/function/stubs/CotStub.kt
index e6bcffd..9217222 100644
--- a/src/main/kotlin/function/stubs/CotStub.kt
+++ b/src/main/kotlin/function/stubs/CotStub.kt
@@ -1,10 +1,58 @@
package function.stubs
import function.trigonometric.ICot
+import kotlin.math.PI
+import kotlin.math.abs
class CotStub : ICot {
+ private val table =
+ mapOf(
+ -PI + 0.1 to -10.0,
+ -PI / 2 to 0.0,
+ -1.0 to -0.6421,
+ -0.5 to -1.8305,
+ 0.5 to 1.8305,
+ 1.0 to 0.6421,
+ PI / 2 to 0.0,
+ PI - 0.1 to 10.0,
+ )
+
override fun cot(
x: Double,
eps: Double,
- ): Double = 1.0
+ ): Double {
+ if (abs(x % PI) < 1e-8) throw ArithmeticException("Cot is undefined at x = k*PI")
+ var nx = x % (2 * PI)
+ if (nx > PI) nx -= 2 * PI
+ if (nx < -PI) nx += 2 * PI
+
+ var closestX = table.keys.first()
+ var minDiff = abs(nx - closestX)
+ for (kx in table.keys) {
+ val diff = abs(nx - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.2) return table[closestX]!!
+
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (nx in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}
diff --git a/src/main/kotlin/function/stubs/CscStub.kt b/src/main/kotlin/function/stubs/CscStub.kt
index 77bcf69..935d767 100644
--- a/src/main/kotlin/function/stubs/CscStub.kt
+++ b/src/main/kotlin/function/stubs/CscStub.kt
@@ -1,10 +1,58 @@
package function.stubs
import function.trigonometric.ICsc
+import kotlin.math.PI
+import kotlin.math.abs
class CscStub : ICsc {
+ private val table =
+ mapOf(
+ -PI + 0.1 to -10.0, // около полюса
+ -PI / 2 to -1.0,
+ -1.0 to -1.1884,
+ -0.5 to -2.0858,
+ 0.5 to 2.0858,
+ 1.0 to 1.1884,
+ PI / 2 to 1.0,
+ PI - 0.1 to 10.0,
+ )
+
override fun csc(
x: Double,
eps: Double,
- ): Double = 1.0
+ ): Double {
+ if (abs(x % PI) < 1e-8) throw ArithmeticException("Csc is undefined at x = k*PI")
+ var nx = x % (2 * PI)
+ if (nx > PI) nx -= 2 * PI
+ if (nx < -PI) nx += 2 * PI
+
+ var closestX = table.keys.first()
+ var minDiff = abs(nx - closestX)
+ for (kx in table.keys) {
+ val diff = abs(nx - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.2) return table[closestX]!!
+
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (nx in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}
diff --git a/src/main/kotlin/function/stubs/LnStub.kt b/src/main/kotlin/function/stubs/LnStub.kt
index d7bd68b..855e25d 100644
--- a/src/main/kotlin/function/stubs/LnStub.kt
+++ b/src/main/kotlin/function/stubs/LnStub.kt
@@ -1,10 +1,55 @@
package function.stubs
import function.base.ILn
+import kotlin.math.E
+import kotlin.math.abs
class LnStub : ILn {
+ private val table =
+ mapOf(
+ 0.1 to -2.302585,
+ 0.5 to -0.693147,
+ 1.0 to 0.0,
+ E to 1.0,
+ 2.0 to 0.693147,
+ 5.0 to 1.609438,
+ 10.0 to 2.302585,
+ 20.0 to 2.995732,
+ )
+
override fun ln(
x: Double,
eps: Double,
- ): Double = 1.0
+ ): Double {
+ if (x <= 0) throw IllegalArgumentException("Ln is undefined for x <= 0")
+ var closestX = table.keys.first()
+ var minDiff = abs(x - closestX)
+ for (kx in table.keys) {
+ val diff = abs(x - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.05) return table[closestX]!!
+
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (x in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (x - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (x - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}
diff --git a/src/main/kotlin/function/stubs/LogStub.kt b/src/main/kotlin/function/stubs/LogStub.kt
index 9e90dbb..8ffc237 100644
--- a/src/main/kotlin/function/stubs/LogStub.kt
+++ b/src/main/kotlin/function/stubs/LogStub.kt
@@ -1,11 +1,58 @@
package function.stubs
import function.logarithmic.ILog
+import kotlin.math.E
+import kotlin.math.abs
+import kotlin.math.log10
class LogStub : ILog {
+ private val table =
+ mapOf(
+ 0.1 to -1.0,
+ 0.5 to -0.3010,
+ 1.0 to 0.0,
+ E to 0.4343,
+ 2.0 to 0.3010,
+ 5.0 to 0.6990,
+ 10.0 to 1.0,
+ 20.0 to 1.3010,
+ )
+
override fun log(
base: Double,
x: Double,
eps: Double,
- ): Double = 1.0
+ ): 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")
+ if (abs(base - 10.0) > 1e-5) return log10(x)
+ var closestX = table.keys.first()
+ var minDiff = abs(x - closestX)
+ for (kx in table.keys) {
+ val diff = abs(x - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.1) return table[closestX]!!
+
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (x in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (x - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (x - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}
diff --git a/src/main/kotlin/function/stubs/SecStub.kt b/src/main/kotlin/function/stubs/SecStub.kt
index 6784997..656598d 100644
--- a/src/main/kotlin/function/stubs/SecStub.kt
+++ b/src/main/kotlin/function/stubs/SecStub.kt
@@ -1,10 +1,61 @@
package function.stubs
import function.trigonometric.ISec
+import kotlin.math.PI
+import kotlin.math.abs
class SecStub : ISec {
+ private val table =
+ mapOf(
+ -PI to -1.0,
+ -PI / 2 + 0.1 to 10.0,
+ -1.0 to 1.8508,
+ -0.5 to 1.1395,
+ 0.0 to 1.0,
+ 0.5 to 1.1395,
+ 1.0 to 1.8508,
+ PI / 2 - 0.1 to 10.0,
+ PI to -1.0,
+ )
+
override fun sec(
x: Double,
eps: Double,
- ): Double = 1.0
+ ): Double {
+ if (abs((x % (2 * PI)) - PI / 2) < 1e-8 || abs((x % (2 * PI)) + PI / 2) < 1e-8) {
+ throw ArithmeticException("Sec is undefined at x = PI/2 + k*PI")
+ }
+ var nx = x % (2 * PI)
+ if (nx > PI) nx -= 2 * PI
+ if (nx < -PI) nx += 2 * PI
+
+ var closestX = table.keys.first()
+ var minDiff = abs(nx - closestX)
+ for (kx in table.keys) {
+ val diff = abs(nx - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.2) return table[closestX]!!
+
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (nx in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}
diff --git a/src/main/kotlin/function/stubs/SinStub.kt b/src/main/kotlin/function/stubs/SinStub.kt
index 1d0a66a..4d4c102 100644
--- a/src/main/kotlin/function/stubs/SinStub.kt
+++ b/src/main/kotlin/function/stubs/SinStub.kt
@@ -1,10 +1,63 @@
package function.stubs
import function.base.ISin
+import kotlin.math.PI
+import kotlin.math.abs
class SinStub : ISin {
+ private val table =
+ mapOf(
+ -PI to 0.0,
+ -PI / 2 to -1.0,
+ -1.0 to -0.8415,
+ -0.5 to -0.4794,
+ 0.0 to 0.0,
+ 0.5 to 0.4794,
+ 1.0 to 0.8415,
+ PI / 2 to 1.0,
+ PI to 0.0,
+ 3.0 to 0.1411,
+ )
+
override fun sin(
x: Double,
eps: Double,
- ): Double = 1.0
+ ): Double {
+ // Нормализация в [-PI, PI]
+ var nx = x % (2 * PI)
+ if (nx > PI) nx -= 2 * PI
+ if (nx < -PI) nx += 2 * PI
+
+ // ближайшая точка в таблице
+ var closestX = table.keys.first()
+ var minDiff = abs(nx - closestX)
+ for (kx in table.keys) {
+ val diff = abs(nx - kx)
+ if (diff < minDiff) {
+ minDiff = diff
+ closestX = kx
+ }
+ }
+ if (minDiff < 0.1) return table[closestX]!!
+
+ // интерполяция линейно
+ val sortedKeys = table.keys.sorted()
+ for (i in 0 until sortedKeys.size - 1) {
+ val k1 = sortedKeys[i]
+ val k2 = sortedKeys[i + 1]
+ if (nx in k1..k2) {
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
+ }
+ // экстраполяция
+ val k1 = sortedKeys[sortedKeys.size - 2]
+ val k2 = sortedKeys.last()
+ val y1 = table[k1]!!
+ val y2 = table[k2]!!
+ val t = (nx - k1) / (k2 - k1)
+ return y1 + t * (y2 - y1)
+ }
}