Implement hyperbolic functions for various Algebras #118

Merged
CommanderTvis merged 14 commits from hyp-trig-functions into dev 2020-08-11 18:18:06 +03:00
6 changed files with 123 additions and 6 deletions
Showing only changes of commit df3bd8a07c - Show all commits

32
CHANGELOG.md Normal file
View File

@ -0,0 +1,32 @@
# KMath
## [Unreleased]
### Added
- Functional Expressions API
- Mathematical Syntax Tree, its interpreter and API
- String to MST parser (https://github.com/mipt-npm/kmath/pull/120)
- MST to JVM bytecode translator (https://github.com/mipt-npm/kmath/pull/94)
- FloatBuffer (specialized MutableBuffer over FloatArray)
- FlaggedBuffer to associate primitive numbers buffer with flags (to mark values infinite or missing, etc.)
- Specialized builder functions for all primitive buffers like `IntBuffer(25) { it + 1 }` (https://github.com/mipt-npm/kmath/pull/125)
- Interface `NumericAlgebra` where `number` operation is available to convert numbers to algebraic elements
- Inverse trigonometric functions support in ExtendedField (`asin`, `acos`, `atan`) (https://github.com/mipt-npm/kmath/pull/114)
- New space extensions: `average` and `averageWith`
- Local coding conventions
- Geometric Domains API in `kmath-core`
- Blocking chains in `kmath-coroutines`
### Changed
- BigInteger and BigDecimal algebra: JBigDecimalField has companion object with default math context; minor optimizations
- `power(T, Int)` extension function has preconditions and supports `Field<T>`
- Memory objects have more preconditions (overflow checking)
- `tg` function is renamed to `tan` (https://github.com/mipt-npm/kmath/pull/114)
- Gradle version: 6.3 -> 6.5.1
- Moved probability distributions to commons-rng and to `kmath-prob`.
### Fixed
- Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106)
- D3.dim value in `kmath-dimensions`
- Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101)
- Commons RNG compatibility (https://github.com/mipt-npm/kmath/issues/93)

View File

@ -61,7 +61,7 @@ inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(bloc
* Represents "semispace", i.e. algebraic structure with associative binary operation called "addition" as well as
* multiplication by scalars.
*
* @param T the type of element of this "semispace".
* @param T the type of element of this semispace.
*/
interface SpaceOperations<T> : Algebra<T> {
/**

View File

@ -4,7 +4,7 @@ package scientifik.kmath.operations
* Returns the sum of all elements in the iterable in this [Space].
*
* @receiver the algebra that provides addition.
* @param data the collection to sum up.
* @param data the iterable to sum up.
* @return the sum.
*/
fun <T> Space<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> add(left, right) }
@ -13,11 +13,29 @@ fun <T> Space<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> ad
* Returns the sum of all elements in the sequence in this [Space].
*
* @receiver the algebra that provides addition.
* @param data the collection to sum up.
* @param data the sequence to sum up.
* @return the sum.
*/
fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> add(left, right) }
/**
* Returns an average value of elements in the iterable in this [Space].
*
* @receiver the algebra that provides addition and division.
* @param data the iterable to find average.
* @return the average value.
*/
fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
/**
* Returns an average value of elements in the sequence in this [Space].
*
* @receiver the algebra that provides addition and division.
* @param data the sequence to find average.
* @return the average value.
*/
fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
/**
* Returns the sum of all elements in the iterable in provided space.
*
@ -25,7 +43,34 @@ fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> ad
* @param space the algebra that provides addition.
* @return the sum.
*/
fun <T : Any, S : Space<T>> Iterable<T>.sumWith(space: S): T = space.sum(this)
fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
/**
* Returns the sum of all elements in the sequence in provided space.
*
* @receiver the collection to sum up.
* @param space the algebra that provides addition.
* @return the sum.
*/
fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
/**
* Returns an average value of elements in the iterable in this [Space].
*
* @receiver the iterable to find average.
* @param space the algebra that provides addition and division.
* @return the average value.
*/
fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
/**
* Returns an average value of elements in the sequence in this [Space].
*
* @receiver the sequence to find average.
* @param space the algebra that provides addition and division.
* @return the average value.
*/
fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
//TODO optimized power operation

View File

@ -40,7 +40,7 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
/**
* A field of [Complex].
*/
object ComplexField : ExtendedField<Complex> {
object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
override val zero: Complex = 0.0.toComplex()
override val one: Complex = 1.0.toComplex()
@ -153,6 +153,8 @@ object ComplexField : ExtendedField<Complex> {
*/
operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this)
override fun norm(arg: Complex): Complex = arg.conjugate * arg
override fun symbol(value: String): Complex = if (value == "i") i else super.symbol(value)
}

View File

@ -1,7 +1,7 @@
package scientifik.kmath.structures
/**
* Specialized [MutableBuffer] implementation over [ShortBuffer].
* Specialized [MutableBuffer] implementation over [ShortArray].
*
* @property array the underlying array.
*/

View File

@ -0,0 +1,38 @@
package scientifik.kmath.operations
import kotlin.test.Test
import kotlin.test.assertEquals
internal class ComplexTest {
@Test
fun conjugate() {
assertEquals(
Complex(0, -42), (ComplexField.i * 42).conjugate
)
}
@Test
fun reciprocal() {
assertEquals(Complex(0.5, -0.0), 2.toComplex().reciprocal)
}
@Test
fun r() {
assertEquals(kotlin.math.sqrt(2.0), (ComplexField.i + 1.0.toComplex()).r)
}
@Test
fun theta() {
assertEquals(0.0, 1.toComplex().theta)
}
@Test
fun toComplex() {
assertEquals(Complex(42, 0), 42.toComplex())
assertEquals(Complex(42.0, 0), 42.0.toComplex())
assertEquals(Complex(42f, 0), 42f.toComplex())
assertEquals(Complex(42.0, 0), 42.0.toComplex())
assertEquals(Complex(42.toByte(), 0), 42.toByte().toComplex())
assertEquals(Complex(42.toShort(), 0), 42.toShort().toComplex())
}
}