Merge remote-tracking branch 'origin/kotlin14' into dev

# Conflicts:
#	build.gradle.kts
#	kmath-core/build.gradle.kts
#	kmath-memory/build.gradle.kts
#	settings.gradle.kts
This commit is contained in:
Alexander Nozik 2020-09-20 10:39:25 +03:00
commit 9617b79647
150 changed files with 2139 additions and 2719 deletions
CHANGELOG.mdREADME.mdbuild.gradle.kts
doc
examples
gradle/wrapper
gradlewgradlew.bat
kmath-ast
build.gradle.kts
src
commonMain/kotlin/scientifik/kmath/ast
jvmMain/kotlin/scientifik/kmath/asm
kmath-commons
build.gradle.kts
src
main/kotlin/scientifik/kmath/commons
test/kotlin/scientifik/kmath/commons/expressions
kmath-core
kmath-coroutines
build.gradle.kts
src
commonMain/kotlin/scientifik/kmath
jvmMain/kotlin/scientifik/kmath
jvmTest/kotlin/scientifik/kmath/streaming
kmath-dimensions
build.gradle.kts
src
commonMain/kotlin/scientifik/kmath/dimensions
commonTest/kotlin/scientifik/dimensions
jsMain/kotlin/scientifik/kmath/dimensions
jvmMain/kotlin/scientifik/kmath/dimensions
kmath-for-real
build.gradle.kts
src/commonMain/kotlin/scientifik/kmath/real

@ -39,7 +39,7 @@
- `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.6
- Gradle version: 6.3 -> 6.6.1
- Moved probability distributions to commons-rng and to `kmath-prob`
### Fixed

@ -54,9 +54,6 @@ can be used for a wide variety of purposes from high performance calculations to
library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free
to submit a feature request if you want something to be done first.
* **Koma wrapper** [Koma](https://github.com/kyonifer/koma) is a well established numerics library in Kotlin, specifically linear algebra.
The plan is to have wrappers for koma implementations for compatibility with kmath API.
## Planned features
* **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks.

@ -1,3 +1,4 @@
plugins { id("ru.mipt.npm.publish") apply false }
plugins {
id("scientifik.publish") apply false
id("org.jetbrains.changelog") version "0.4.0"
@ -17,20 +18,6 @@ allprojects {
group = "kscience.kmath"
version = kmathVersion
afterEvaluate {
extensions.findByType<org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension>()?.run {
targets.all {
sourceSets.all {
languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
}
}
}
}
}
subprojects {
if (name.startsWith("kmath")) {
apply(plugin = "scientifik.publish")
}
}
subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") }

@ -12,6 +12,3 @@ api and multiple library back-ends.
* [Expressions](./expressions.md)
* Commons math integration
* Koma integration

@ -1,58 +1,48 @@
import org.jetbrains.kotlin.allopen.gradle.AllOpenExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
java
kotlin("jvm")
kotlin("plugin.allopen") version "1.3.72"
id("kotlinx.benchmark") version "0.2.0-dev-8"
kotlin("plugin.allopen") version "1.4.20-dev-3898-14"
id("kotlinx.benchmark") version "0.2.0-dev-20"
}
configure<AllOpenExtension> {
annotation("org.openjdk.jmh.annotations.State")
}
allOpen.annotation("org.openjdk.jmh.annotations.State")
repositories {
maven("http://dl.bintray.com/kyonifer/maven")
maven("https://dl.bintray.com/mipt-npm/scientifik")
maven("https://dl.bintray.com/mipt-npm/dev")
maven("https://dl.bintray.com/kotlin/kotlin-dev/")
mavenCentral()
}
sourceSets {
register("benchmarks")
}
sourceSets.register("benchmarks")
dependencies {
implementation(project(":kmath-ast"))
// implementation(project(":kmath-ast"))
implementation(project(":kmath-core"))
implementation(project(":kmath-coroutines"))
implementation(project(":kmath-commons"))
implementation(project(":kmath-prob"))
implementation(project(":kmath-koma"))
implementation(project(":kmath-viktor"))
implementation(project(":kmath-dimensions"))
implementation("com.kyonifer:koma-core-ejml:0.12")
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6")
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-8")
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20")
"benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath
}
// Configure benchmark
benchmark {
// Setup configurations
targets {
targets
// This one matches sourceSet name above
register("benchmarks")
}
.register("benchmarks")
configurations {
register("fast") {
warmups = 5 // number of warmup iterations
iterations = 3 // number of iterations
iterationTime = 500 // time in seconds per iteration
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
}
configurations.register("fast") {
warmups = 5 // number of warmup iterations
iterations = 3 // number of iterations
iterationTime = 500 // time in seconds per iteration
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
}
}
@ -63,9 +53,4 @@ kotlin.sourceSets.all {
}
}
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = Scientifik.JVM_TARGET.toString()
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"
}
}
tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "11" }

@ -5,44 +5,33 @@ import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import java.nio.IntBuffer
@State(Scope.Benchmark)
class ArrayBenchmark {
@Benchmark
fun benchmarkArrayRead() {
var res = 0
for (i in 1..size) {
res += array[size - i]
}
for (i in 1..size) res += array[size - i]
}
@Benchmark
fun benchmarkBufferRead() {
var res = 0
for (i in 1..size) {
res += arrayBuffer.get(size - i)
}
for (i in 1..size) res += arrayBuffer.get(size - i)
}
@Benchmark
fun nativeBufferRead() {
var res = 0
for (i in 1..size) {
res += nativeBuffer.get(size - i)
}
for (i in 1..size) res += nativeBuffer.get(size - i)
}
companion object {
val size = 1000
val array = IntArray(size) { it }
val arrayBuffer = IntBuffer.wrap(array)
val nativeBuffer = IntBuffer.allocate(size).also {
for (i in 0 until size) {
it.put(i, i)
}
const val size: Int = 1000
val array: IntArray = IntArray(size) { it }
val arrayBuffer: IntBuffer = IntBuffer.wrap(array)
val nativeBuffer: IntBuffer = IntBuffer.allocate(size).also {
for (i in 0 until size) it.put(i, i)
}
}
}
}

@ -1,70 +1,70 @@
package scientifik.kmath.ast
import scientifik.kmath.asm.compile
import scientifik.kmath.expressions.Expression
import scientifik.kmath.expressions.expressionInField
import scientifik.kmath.expressions.invoke
import scientifik.kmath.operations.Field
import scientifik.kmath.operations.RealField
import kotlin.random.Random
import kotlin.system.measureTimeMillis
class ExpressionsInterpretersBenchmark {
private val algebra: Field<Double> = RealField
fun functionalExpression() {
val expr = algebra.expressionInField {
variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0)
}
invokeAndSum(expr)
}
fun mstExpression() {
val expr = algebra.mstInField {
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
}
invokeAndSum(expr)
}
fun asmExpression() {
val expr = algebra.mstInField {
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
}.compile()
invokeAndSum(expr)
}
private fun invokeAndSum(expr: Expression<Double>) {
val random = Random(0)
var sum = 0.0
repeat(1000000) {
sum += expr("x" to random.nextDouble())
}
println(sum)
}
}
fun main() {
val benchmark = ExpressionsInterpretersBenchmark()
val fe = measureTimeMillis {
benchmark.functionalExpression()
}
println("fe=$fe")
val mst = measureTimeMillis {
benchmark.mstExpression()
}
println("mst=$mst")
val asm = measureTimeMillis {
benchmark.asmExpression()
}
println("asm=$asm")
}
//package scientifik.kmath.ast
//
//import scientifik.kmath.asm.compile
//import scientifik.kmath.expressions.Expression
//import scientifik.kmath.expressions.expressionInField
//import scientifik.kmath.expressions.invoke
//import scientifik.kmath.operations.Field
//import scientifik.kmath.operations.RealField
//import kotlin.random.Random
//import kotlin.system.measureTimeMillis
//
//class ExpressionsInterpretersBenchmark {
// private val algebra: Field<Double> = RealField
// fun functionalExpression() {
// val expr = algebra.expressionInField {
// variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0)
// }
//
// invokeAndSum(expr)
// }
//
// fun mstExpression() {
// val expr = algebra.mstInField {
// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
// }
//
// invokeAndSum(expr)
// }
//
// fun asmExpression() {
// val expr = algebra.mstInField {
// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
// }.compile()
//
// invokeAndSum(expr)
// }
//
// private fun invokeAndSum(expr: Expression<Double>) {
// val random = Random(0)
// var sum = 0.0
//
// repeat(1000000) {
// sum += expr("x" to random.nextDouble())
// }
//
// println(sum)
// }
//}
//
//fun main() {
// val benchmark = ExpressionsInterpretersBenchmark()
//
// val fe = measureTimeMillis {
// benchmark.functionalExpression()
// }
//
// println("fe=$fe")
//
// val mst = measureTimeMillis {
// benchmark.mstExpression()
// }
//
// println("mst=$mst")
//
// val asm = measureTimeMillis {
// benchmark.asmExpression()
// }
//
// println("asm=$asm")
//}

@ -1,55 +0,0 @@
package scientifik.kmath.linear
import koma.matrix.ejml.EJMLMatrixFactory
import scientifik.kmath.commons.linear.CMMatrixContext
import scientifik.kmath.commons.linear.inverse
import scientifik.kmath.commons.linear.toCM
import scientifik.kmath.operations.RealField
import scientifik.kmath.operations.invoke
import scientifik.kmath.structures.Matrix
import kotlin.contracts.ExperimentalContracts
import kotlin.random.Random
import kotlin.system.measureTimeMillis
@ExperimentalContracts
fun main() {
val random = Random(1224)
val dim = 100
//creating invertible matrix
val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
val matrix = l dot u
val n = 5000 // iterations
MatrixContext.real {
repeat(50) { val res = inverse(matrix) }
val inverseTime = measureTimeMillis { repeat(n) { val res = inverse(matrix) } }
println("[kmath] Inversion of $n matrices $dim x $dim finished in $inverseTime millis")
}
//commons-math
val commonsTime = measureTimeMillis {
CMMatrixContext {
val cm = matrix.toCM() //avoid overhead on conversion
repeat(n) { val res = inverse(cm) }
}
}
println("[commons-math] Inversion of $n matrices $dim x $dim finished in $commonsTime millis")
//koma-ejml
val komaTime = measureTimeMillis {
(KomaMatrixContext(EJMLMatrixFactory(), RealField)) {
val km = matrix.toKoma() //avoid overhead on conversion
repeat(n) {
val res = inverse(km)
}
}
}
println("[koma-ejml] Inversion of $n matrices $dim x $dim finished in $komaTime millis")
}

@ -1,49 +0,0 @@
package scientifik.kmath.linear
import koma.matrix.ejml.EJMLMatrixFactory
import scientifik.kmath.commons.linear.CMMatrixContext
import scientifik.kmath.commons.linear.toCM
import scientifik.kmath.operations.RealField
import scientifik.kmath.operations.invoke
import scientifik.kmath.structures.Matrix
import kotlin.random.Random
import kotlin.system.measureTimeMillis
fun main() {
val random = Random(12224)
val dim = 1000
//creating invertible matrix
val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
// //warmup
// matrix1 dot matrix2
CMMatrixContext {
val cmMatrix1 = matrix1.toCM()
val cmMatrix2 = matrix2.toCM()
val cmTime = measureTimeMillis {
cmMatrix1 dot cmMatrix2
}
println("CM implementation time: $cmTime")
}
(KomaMatrixContext(EJMLMatrixFactory(), RealField)) {
val komaMatrix1 = matrix1.toKoma()
val komaMatrix2 = matrix2.toKoma()
val komaTime = measureTimeMillis {
komaMatrix1 dot komaMatrix2
}
println("Koma-ejml implementation time: $komaTime")
}
val genericTime = measureTimeMillis {
val res = matrix1 dot matrix2
}
println("Generic implementation time: $genericTime")
}

@ -2,7 +2,7 @@ package scientifik.kmath.structures
import kotlin.system.measureTimeMillis
fun main(args: Array<String>) {
fun main() {
val n = 6000
val array = DoubleArray(n * n) { 1.0 }

@ -2,9 +2,7 @@ package scientifik.kmath.structures
import kotlin.system.measureTimeMillis
fun main(args: Array<String>) {
fun main() {
val n = 6000
val structure = NDStructure.build(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 }

Binary file not shown.

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

2
gradlew vendored

@ -130,7 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath

21
gradlew.bat vendored

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,21 +64,6 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

@ -1,8 +1,6 @@
plugins { id("scientifik.mpp") }
plugins { id("ru.mipt.npm.mpp") }
kotlin.sourceSets {
all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") }
commonMain {
dependencies {
api(project(":kmath-core"))
@ -17,4 +15,4 @@ kotlin.sourceSets {
implementation(kotlin("reflect"))
}
}
}
}

@ -7,20 +7,20 @@ import scientifik.kmath.operations.RealField
/**
* A Mathematical Syntax Tree node for mathematical expressions.
*/
sealed class MST {
public sealed class MST {
/**
* A node containing raw string.
*
* @property value the value of this node.
*/
data class Symbolic(val value: String) : MST()
public data class Symbolic(val value: String) : MST()
/**
* A node containing a numeric value or scalar.
*
* @property value the value of this number.
*/
data class Numeric(val value: Number) : MST()
public data class Numeric(val value: Number) : MST()
/**
* A node containing an unary operation.
@ -28,9 +28,7 @@ sealed class MST {
* @property operation the identifier of operation.
* @property value the argument of this operation.
*/
data class Unary(val operation: String, val value: MST) : MST() {
companion object
}
public data class Unary(val operation: String, val value: MST) : MST()
/**
* A node containing binary operation.
@ -39,9 +37,7 @@ sealed class MST {
* @property left the left operand.
* @property right the right operand.
*/
data class Binary(val operation: String, val left: MST, val right: MST) : MST() {
companion object
}
public data class Binary(val operation: String, val left: MST, val right: MST) : MST()
}
// TODO add a function with named arguments
@ -53,7 +49,7 @@ sealed class MST {
* @param node the node to evaluate.
* @return the value of expression.
*/
fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
?: error("Numeric nodes are not supported by $this")
is MST.Symbolic -> symbol(node.value)
@ -84,4 +80,4 @@ fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
* @param algebra the algebra that provides operations.
* @return the value of expression.
*/
fun <T> MST.interpret(algebra: Algebra<T>): T = algebra.evaluate(this)
public fun <T> MST.interpret(algebra: Algebra<T>): T = algebra.evaluate(this)

@ -5,7 +5,7 @@ import scientifik.kmath.operations.*
/**
* [Algebra] over [MST] nodes.
*/
object MstAlgebra : NumericAlgebra<MST> {
public object MstAlgebra : NumericAlgebra<MST> {
override fun number(value: Number): MST = MST.Numeric(value)
override fun symbol(value: String): MST = MST.Symbolic(value)
@ -20,7 +20,7 @@ object MstAlgebra : NumericAlgebra<MST> {
/**
* [Space] over [MST] nodes.
*/
object MstSpace : Space<MST>, NumericAlgebra<MST> {
public object MstSpace : Space<MST>, NumericAlgebra<MST> {
override val zero: MST = number(0.0)
override fun number(value: Number): MST = MstAlgebra.number(value)
@ -37,7 +37,7 @@ object MstSpace : Space<MST>, NumericAlgebra<MST> {
/**
* [Ring] over [MST] nodes.
*/
object MstRing : Ring<MST>, NumericAlgebra<MST> {
public object MstRing : Ring<MST>, NumericAlgebra<MST> {
override val zero: MST = number(0.0)
override val one: MST = number(1.0)
@ -58,18 +58,18 @@ object MstRing : Ring<MST>, NumericAlgebra<MST> {
/**
* [Field] over [MST] nodes.
*/
object MstField : Field<MST> {
override val zero: MST = number(0.0)
override val one: MST = number(1.0)
public object MstField : Field<MST> {
public override val zero: MST = number(0.0)
public override val one: MST = number(1.0)
override fun symbol(value: String): MST = MstRing.symbol(value)
override fun number(value: Number): MST = MstRing.number(value)
override fun add(a: MST, b: MST): MST = MstRing.add(a, b)
override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k)
override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b)
override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION, a, b)
public override fun symbol(value: String): MST = MstRing.symbol(value)
public override fun number(value: Number): MST = MstRing.number(value)
public override fun add(a: MST, b: MST): MST = MstRing.add(a, b)
public override fun multiply(a: MST, k: Number): MST = MstRing.multiply(a, k)
public override fun multiply(a: MST, b: MST): MST = MstRing.multiply(a, b)
public override fun divide(a: MST, b: MST): MST = binaryOperation(FieldOperations.DIV_OPERATION, a, b)
override fun binaryOperation(operation: String, left: MST, right: MST): MST =
public override fun binaryOperation(operation: String, left: MST, right: MST): MST =
MstRing.binaryOperation(operation, left, right)
override fun unaryOperation(operation: String, arg: MST): MST = MstRing.unaryOperation(operation, arg)
@ -78,7 +78,7 @@ object MstField : Field<MST> {
/**
* [ExtendedField] over [MST] nodes.
*/
object MstExtendedField : ExtendedField<MST> {
public object MstExtendedField : ExtendedField<MST> {
override val zero: MST = number(0.0)
override val one: MST = number(1.0)

@ -2,7 +2,6 @@ package scientifik.kmath.ast
import scientifik.kmath.expressions.*
import scientifik.kmath.operations.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@ -13,7 +12,7 @@ import kotlin.contracts.contract
* @property algebra the algebra that provides operations.
* @property mst the [MST] node.
*/
class MstExpression<T>(val algebra: Algebra<T>, val mst: MST) : Expression<T> {
public class MstExpression<T>(public val algebra: Algebra<T>, public val mst: MST) : Expression<T> {
private inner class InnerAlgebra(val arguments: Map<String, T>) : NumericAlgebra<T> {
override fun symbol(value: String): T = arguments[value] ?: algebra.symbol(value)
override fun unaryOperation(operation: String, arg: T): T = algebra.unaryOperation(operation, arg)
@ -33,7 +32,7 @@ class MstExpression<T>(val algebra: Algebra<T>, val mst: MST) : Expression<T> {
/**
* Builds [MstExpression] over [Algebra].
*/
inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
mstAlgebra: E,
block: E.() -> MST
): MstExpression<T> = MstExpression(this, mstAlgebra.block())
@ -41,7 +40,7 @@ inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
/**
* Builds [MstExpression] over [Space].
*/
inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
public inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return MstExpression(this, MstSpace.block())
}
@ -49,7 +48,7 @@ inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): Mst
/**
* Builds [MstExpression] over [Ring].
*/
inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
public inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return MstExpression(this, MstRing.block())
}
@ -57,7 +56,7 @@ inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExp
/**
* Builds [MstExpression] over [Field].
*/
inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): MstExpression<T> {
public inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return MstExpression(this, MstField.block())
}
@ -65,7 +64,7 @@ inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): Mst
/**
* Builds [MstExpression] over [ExtendedField].
*/
inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
public inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return MstExpression(this, MstExtendedField.block())
}
@ -73,7 +72,7 @@ inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField
/**
* Builds [MstExpression] over [FunctionalExpressionSpace].
*/
inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return algebra.mstInSpace(block)
}
@ -81,7 +80,7 @@ inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstIn
/**
* Builds [MstExpression] over [FunctionalExpressionRing].
*/
inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
public inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return algebra.mstInRing(block)
}
@ -89,7 +88,7 @@ inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRi
/**
* Builds [MstExpression] over [FunctionalExpressionField].
*/
inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstInField(block: MstField.() -> MST): MstExpression<T> {
public inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstInField(block: MstField.() -> MST): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return algebra.mstInField(block)
}
@ -97,7 +96,9 @@ inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstIn
/**
* Builds [MstExpression] over [FunctionalExpressionExtendedField].
*/
inline fun <reified T : Any, A : ExtendedField<T>> FunctionalExpressionExtendedField<T, A>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
public inline fun <reified T : Any, A : ExtendedField<T>> FunctionalExpressionExtendedField<T, A>.mstInExtendedField(
block: MstExtendedField.() -> MST
): MstExpression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return algebra.mstInExtendedField(block)
}

@ -18,7 +18,7 @@ import scientifik.kmath.operations.SpaceOperations
/**
* TODO move to core
*/
object ArithmeticsEvaluator : Grammar<MST>() {
public object ArithmeticsEvaluator : Grammar<MST>() {
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?")
private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*")
@ -35,23 +35,23 @@ object ArithmeticsEvaluator : Grammar<MST>() {
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
private val singular: Parser<MST> by id use { MST.Symbolic(text) }
private val unaryFunction: Parser<MST> by (id and skip(lpar) and parser(::subSumChain) and skip(rpar))
private val unaryFunction: Parser<MST> by (id and -lpar and parser(::subSumChain) and -rpar)
.map { (id, term) -> MST.Unary(id.text, term) }
private val binaryFunction: Parser<MST> by id
.and(skip(lpar))
.and(-lpar)
.and(parser(::subSumChain))
.and(skip(comma))
.and(-comma)
.and(parser(::subSumChain))
.and(skip(rpar))
.and(-rpar)
.map { (id, left, right) -> MST.Binary(id.text, left, right) }
private val term: Parser<MST> by number
.or(binaryFunction)
.or(unaryFunction)
.or(singular)
.or(skip(minus) and parser(::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) })
.or(skip(lpar) and parser(::subSumChain) and skip(rpar))
.or(-minus and parser(::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) })
.or(-lpar and parser(::subSumChain) and -rpar)
private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b ->
MST.Binary(PowerOperations.POW_OPERATION, a, b)
@ -86,7 +86,7 @@ object ArithmeticsEvaluator : Grammar<MST>() {
* @receiver the string to parse.
* @return the [MST] node.
*/
fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
public fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
/**
* Parses the string into [MST].
@ -94,4 +94,4 @@ fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd
* @receiver the string to parse.
* @return the [MST] node.
*/
fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this)
public fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this)

@ -13,7 +13,7 @@ import kotlin.reflect.KClass
/**
* Compile given MST to an Expression using AST compiler
*/
fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<T> {
public fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<T> {
fun AsmBuilder<T>.visit(node: MST) {
when (node) {
is MST.Symbolic -> {
@ -56,9 +56,9 @@ fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<
/**
* Compile an [MST] to ASM using given algebra
*/
inline fun <reified T : Any> Algebra<T>.expression(mst: MST): Expression<T> = mst.compileWith(T::class, this)
public inline fun <reified T : Any> Algebra<T>.expression(mst: MST): Expression<T> = mst.compileWith(T::class, this)
/**
* Optimize performance of an [MstExpression] using ASM codegen
*/
inline fun <reified T : Any> MstExpression<T>.compile(): Expression<T> = mst.compileWith(T::class, algebra)
public inline fun <reified T : Any> MstExpression<T>.compile(): Expression<T> = mst.compileWith(T::class, algebra)

@ -1,12 +1,10 @@
plugins { id("scientifik.jvm") }
plugins { id("ru.mipt.npm.jvm") }
description = "Commons math binding for kmath"
dependencies {
api(project(":kmath-core"))
api(project(":kmath-coroutines"))
api(project(":kmath-prob"))
api(project(":kmath-functions"))
// api(project(":kmath-functions"))
api("org.apache.commons:commons-math3:3.6.1")
}
kotlin.sourceSets.all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") }

@ -7,131 +7,122 @@ import scientifik.kmath.operations.ExtendedField
import scientifik.kmath.operations.Field
import scientifik.kmath.operations.invoke
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
/**
* A field wrapping commons-math derivative structures
*/
class DerivativeStructureField(
val order: Int,
val parameters: Map<String, Double>
public class DerivativeStructureField(
public val order: Int,
public val parameters: Map<String, Double>
) : ExtendedField<DerivativeStructure> {
override val zero: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size) }
override val one: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size, 1.0) }
public override val zero: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size) }
public override val one: DerivativeStructure by lazy { DerivativeStructure(order, parameters.size, 1.0) }
private val variables: Map<String, DerivativeStructure> = parameters.mapValues { (key, value) ->
DerivativeStructure(parameters.size, order, parameters.keys.indexOf(key), value)
}
val variable: ReadOnlyProperty<Any?, DerivativeStructure> = object : ReadOnlyProperty<Any?, DerivativeStructure> {
override fun getValue(thisRef: Any?, property: KProperty<*>): DerivativeStructure =
variables[property.name] ?: error("A variable with name ${property.name} does not exist")
public val variable: ReadOnlyProperty<Any?, DerivativeStructure> = ReadOnlyProperty { _, property ->
variables[property.name] ?: error("A variable with name ${property.name} does not exist")
}
fun variable(name: String, default: DerivativeStructure? = null): DerivativeStructure =
public fun variable(name: String, default: DerivativeStructure? = null): DerivativeStructure =
variables[name] ?: default ?: error("A variable with name $name does not exist")
fun Number.const(): DerivativeStructure = DerivativeStructure(order, parameters.size, toDouble())
public fun Number.const(): DerivativeStructure = DerivativeStructure(order, parameters.size, toDouble())
fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double {
public fun DerivativeStructure.deriv(parName: String, order: Int = 1): Double {
return deriv(mapOf(parName to order))
}
fun DerivativeStructure.deriv(orders: Map<String, Int>): Double {
public fun DerivativeStructure.deriv(orders: Map<String, Int>): Double {
return getPartialDerivative(*parameters.keys.map { orders[it] ?: 0 }.toIntArray())
}
fun DerivativeStructure.deriv(vararg orders: Pair<String, Int>): Double = deriv(mapOf(*orders))
public fun DerivativeStructure.deriv(vararg orders: Pair<String, Int>): Double = deriv(mapOf(*orders))
public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) {
public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) {
is Double -> a.multiply(k)
is Int -> a.multiply(k)
else -> a.multiply(k.toDouble())
}
override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)
public override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.sin()
public override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.cos()
public override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.tan()
public override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin()
public override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos()
public override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan()
public override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh()
public override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh()
public override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh()
public override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.asinh()
public override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.acosh()
public override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.atanh()
override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)
override fun sin(arg: DerivativeStructure): DerivativeStructure = arg.sin()
override fun cos(arg: DerivativeStructure): DerivativeStructure = arg.cos()
override fun tan(arg: DerivativeStructure): DerivativeStructure = arg.tan()
override fun asin(arg: DerivativeStructure): DerivativeStructure = arg.asin()
override fun acos(arg: DerivativeStructure): DerivativeStructure = arg.acos()
override fun atan(arg: DerivativeStructure): DerivativeStructure = arg.atan()
override fun sinh(arg: DerivativeStructure): DerivativeStructure = arg.sinh()
override fun cosh(arg: DerivativeStructure): DerivativeStructure = arg.cosh()
override fun tanh(arg: DerivativeStructure): DerivativeStructure = arg.tanh()
override fun asinh(arg: DerivativeStructure): DerivativeStructure = arg.asinh()
override fun acosh(arg: DerivativeStructure): DerivativeStructure = arg.acosh()
override fun atanh(arg: DerivativeStructure): DerivativeStructure = arg.atanh()
override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) {
public override fun power(arg: DerivativeStructure, pow: Number): DerivativeStructure = when (pow) {
is Double -> arg.pow(pow)
is Int -> arg.pow(pow)
else -> arg.pow(pow.toDouble())
}
fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow)
override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp()
override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log()
public fun power(arg: DerivativeStructure, pow: DerivativeStructure): DerivativeStructure = arg.pow(pow)
public override fun exp(arg: DerivativeStructure): DerivativeStructure = arg.exp()
public override fun ln(arg: DerivativeStructure): DerivativeStructure = arg.log()
override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble())
override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble())
override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this
override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this
public override operator fun DerivativeStructure.plus(b: Number): DerivativeStructure = add(b.toDouble())
public override operator fun DerivativeStructure.minus(b: Number): DerivativeStructure = subtract(b.toDouble())
public override operator fun Number.plus(b: DerivativeStructure): DerivativeStructure = b + this
public override operator fun Number.minus(b: DerivativeStructure): DerivativeStructure = b - this
}
/**
* A constructs that creates a derivative structure with required order on-demand
*/
class DiffExpression(val function: DerivativeStructureField.() -> DerivativeStructure) : Expression<Double> {
override operator fun invoke(arguments: Map<String, Double>): Double = DerivativeStructureField(
public class DiffExpression(public val function: DerivativeStructureField.() -> DerivativeStructure) :
Expression<Double> {
public override operator fun invoke(arguments: Map<String, Double>): Double = DerivativeStructureField(
0,
arguments
).run(function).value
).function().value
/**
* Get the derivative expression with given orders
* TODO make result [DiffExpression]
*/
fun derivative(orders: Map<String, Int>): Expression<Double> = object : Expression<Double> {
override operator fun invoke(arguments: Map<String, Double>): Double =
(DerivativeStructureField(orders.values.max() ?: 0, arguments)) { function().deriv(orders) }
public fun derivative(orders: Map<String, Int>): Expression<Double> = Expression { arguments ->
(DerivativeStructureField(orders.values.max() ?: 0, arguments)) { function().deriv(orders) }
}
//TODO add gradient and maybe other vector operators
}
fun DiffExpression.derivative(vararg orders: Pair<String, Int>): Expression<Double> = derivative(mapOf(*orders))
fun DiffExpression.derivative(name: String): Expression<Double> = derivative(name to 1)
public fun DiffExpression.derivative(vararg orders: Pair<String, Int>): Expression<Double> = derivative(mapOf(*orders))
public fun DiffExpression.derivative(name: String): Expression<Double> = derivative(name to 1)
/**
* A context for [DiffExpression] (not to be confused with [DerivativeStructure])
*/
object DiffExpressionAlgebra : ExpressionAlgebra<Double, DiffExpression>, Field<DiffExpression> {
override fun variable(name: String, default: Double?): DiffExpression =
public object DiffExpressionAlgebra : ExpressionAlgebra<Double, DiffExpression>, Field<DiffExpression> {
public override val zero: DiffExpression = DiffExpression { 0.0.const() }
public override val one: DiffExpression = DiffExpression { 1.0.const() }
public override fun variable(name: String, default: Double?): DiffExpression =
DiffExpression { variable(name, default?.const()) }
override fun const(value: Double): DiffExpression =
DiffExpression { value.const() }
public override fun const(value: Double): DiffExpression = DiffExpression { value.const() }
override fun add(a: DiffExpression, b: DiffExpression): DiffExpression =
public override fun add(a: DiffExpression, b: DiffExpression): DiffExpression =
DiffExpression { a.function(this) + b.function(this) }
override val zero: DiffExpression = DiffExpression { 0.0.const() }
public override fun multiply(a: DiffExpression, k: Number): DiffExpression = DiffExpression { a.function(this) * k }
override fun multiply(a: DiffExpression, k: Number): DiffExpression =
DiffExpression { a.function(this) * k }
override val one: DiffExpression = DiffExpression { 1.0.const() }
override fun multiply(a: DiffExpression, b: DiffExpression): DiffExpression =
public override fun multiply(a: DiffExpression, b: DiffExpression): DiffExpression =
DiffExpression { a.function(this) * b.function(this) }
override fun divide(a: DiffExpression, b: DiffExpression): DiffExpression =
public override fun divide(a: DiffExpression, b: DiffExpression): DiffExpression =
DiffExpression { a.function(this) / b.function(this) }
}

@ -5,32 +5,32 @@ import scientifik.kmath.linear.*
import scientifik.kmath.structures.Matrix
import scientifik.kmath.structures.NDStructure
class CMMatrix(val origin: RealMatrix, features: Set<MatrixFeature>? = null) :
public class CMMatrix(public val origin: RealMatrix, features: Set<MatrixFeature>? = null) :
FeaturedMatrix<Double> {
override val rowNum: Int get() = origin.rowDimension
override val colNum: Int get() = origin.columnDimension
public override val rowNum: Int get() = origin.rowDimension
public override val colNum: Int get() = origin.columnDimension
override val features: Set<MatrixFeature> = features ?: sequence<MatrixFeature> {
public override val features: Set<MatrixFeature> = features ?: sequence<MatrixFeature> {
if (origin is DiagonalMatrix) yield(DiagonalFeature)
}.toHashSet()
override fun suggestFeature(vararg features: MatrixFeature): CMMatrix =
public override fun suggestFeature(vararg features: MatrixFeature): CMMatrix =
CMMatrix(origin, this.features + features)
override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
override fun equals(other: Any?): Boolean {
public override fun equals(other: Any?): Boolean {
return NDStructure.equals(this, other as? NDStructure<*> ?: return false)
}
override fun hashCode(): Int {
public override fun hashCode(): Int {
var result = origin.hashCode()
result = 31 * result + features.hashCode()
return result
}
}
fun Matrix<Double>.toCM(): CMMatrix = if (this is CMMatrix) {
public fun Matrix<Double>.toCM(): CMMatrix = if (this is CMMatrix) {
this
} else {
//TODO add feature analysis
@ -38,56 +38,56 @@ fun Matrix<Double>.toCM(): CMMatrix = if (this is CMMatrix) {
CMMatrix(Array2DRowRealMatrix(array))
}
fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this)
public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this)
class CMVector(val origin: RealVector) : Point<Double> {
override val size: Int get() = origin.dimension
public class CMVector(public val origin: RealVector) : Point<Double> {
public override val size: Int get() = origin.dimension
override operator fun get(index: Int): Double = origin.getEntry(index)
public override operator fun get(index: Int): Double = origin.getEntry(index)
override operator fun iterator(): Iterator<Double> = origin.toArray().iterator()
public override operator fun iterator(): Iterator<Double> = origin.toArray().iterator()
}
fun Point<Double>.toCM(): CMVector = if (this is CMVector) this else {
public fun Point<Double>.toCM(): CMVector = if (this is CMVector) this else {
val array = DoubleArray(size) { this[it] }
CMVector(ArrayRealVector(array))
}
fun RealVector.toPoint(): CMVector = CMVector(this)
public fun RealVector.toPoint(): CMVector = CMVector(this)
object CMMatrixContext : MatrixContext<Double> {
override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix {
public object CMMatrixContext : MatrixContext<Double> {
public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix {
val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } }
return CMMatrix(Array2DRowRealMatrix(array))
}
override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix =
CMMatrix(this.toCM().origin.multiply(other.toCM().origin))
public override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix =
CMMatrix(toCM().origin.multiply(other.toCM().origin))
override fun Matrix<Double>.dot(vector: Point<Double>): CMVector =
CMVector(this.toCM().origin.preMultiply(vector.toCM().origin))
public override fun Matrix<Double>.dot(vector: Point<Double>): CMVector =
CMVector(toCM().origin.preMultiply(vector.toCM().origin))
override operator fun Matrix<Double>.unaryMinus(): CMMatrix =
public override operator fun Matrix<Double>.unaryMinus(): CMMatrix =
produce(rowNum, colNum) { i, j -> -get(i, j) }
override fun add(a: Matrix<Double>, b: Matrix<Double>): CMMatrix =
public override fun add(a: Matrix<Double>, b: Matrix<Double>): CMMatrix =
CMMatrix(a.toCM().origin.multiply(b.toCM().origin))
override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix =
CMMatrix(this.toCM().origin.subtract(b.toCM().origin))
public override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix =
CMMatrix(toCM().origin.subtract(b.toCM().origin))
override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble()))
override operator fun Matrix<Double>.times(value: Double): Matrix<Double> =
public override operator fun Matrix<Double>.times(value: Double): Matrix<Double> =
produce(rowNum, colNum) { i, j -> get(i, j) * value }
}
operator fun CMMatrix.plus(other: CMMatrix): CMMatrix =
CMMatrix(this.origin.add(other.origin))
public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix =
CMMatrix(origin.add(other.origin))
operator fun CMMatrix.minus(other: CMMatrix): CMMatrix =
CMMatrix(this.origin.subtract(other.origin))
public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix =
CMMatrix(origin.subtract(other.origin))
infix fun CMMatrix.dot(other: CMMatrix): CMMatrix =
CMMatrix(this.origin.multiply(other.origin))
public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix =
CMMatrix(origin.multiply(other.origin))

@ -4,7 +4,7 @@ import org.apache.commons.math3.linear.*
import scientifik.kmath.linear.Point
import scientifik.kmath.structures.Matrix
enum class CMDecomposition {
public enum class CMDecomposition {
LUP,
QR,
RRQR,
@ -12,29 +12,30 @@ enum class CMDecomposition {
CHOLESKY
}
public fun CMMatrixContext.solver(
a: Matrix<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP
): DecompositionSolver = when (decomposition) {
CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver
CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver
CMDecomposition.QR -> QRDecomposition(a.toCM().origin).solver
CMDecomposition.EIGEN -> EigenDecomposition(a.toCM().origin).solver
CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver
}
fun CMMatrixContext.solver(a: Matrix<Double>, decomposition: CMDecomposition = CMDecomposition.LUP) =
when (decomposition) {
CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver
CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver
CMDecomposition.QR -> QRDecomposition(a.toCM().origin).solver
CMDecomposition.EIGEN -> EigenDecomposition(a.toCM().origin).solver
CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver
}
fun CMMatrixContext.solve(
public fun CMMatrixContext.solve(
a: Matrix<Double>,
b: Matrix<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP
) = solver(a, decomposition).solve(b.toCM().origin).asMatrix()
): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).asMatrix()
fun CMMatrixContext.solve(
public fun CMMatrixContext.solve(
a: Matrix<Double>,
b: Point<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP
) = solver(a, decomposition).solve(b.toCM().origin).toPoint()
): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint()
fun CMMatrixContext.inverse(
public fun CMMatrixContext.inverse(
a: Matrix<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP
) = solver(a, decomposition).inverse.asMatrix()
): CMMatrix = solver(a, decomposition).inverse.asMatrix()

@ -2,32 +2,32 @@ package scientifik.kmath.commons.random
import scientifik.kmath.prob.RandomGenerator
class CMRandomGeneratorWrapper(val factory: (IntArray) -> RandomGenerator) :
public class CMRandomGeneratorWrapper(public val factory: (IntArray) -> RandomGenerator) :
org.apache.commons.math3.random.RandomGenerator {
private var generator: RandomGenerator = factory(intArrayOf())
override fun nextBoolean(): Boolean = generator.nextBoolean()
override fun nextFloat(): Float = generator.nextDouble().toFloat()
public override fun nextBoolean(): Boolean = generator.nextBoolean()
public override fun nextFloat(): Float = generator.nextDouble().toFloat()
override fun setSeed(seed: Int) {
public override fun setSeed(seed: Int) {
generator = factory(intArrayOf(seed))
}
override fun setSeed(seed: IntArray) {
public override fun setSeed(seed: IntArray) {
generator = factory(seed)
}
override fun setSeed(seed: Long) {
public override fun setSeed(seed: Long) {
setSeed(seed.toInt())
}
override fun nextBytes(bytes: ByteArray) {
public override fun nextBytes(bytes: ByteArray) {
generator.fillBytes(bytes)
}
override fun nextInt(): Int = generator.nextInt()
override fun nextInt(n: Int): Int = generator.nextInt(n)
override fun nextGaussian(): Double = TODO()
override fun nextDouble(): Double = generator.nextDouble()
override fun nextLong(): Long = generator.nextLong()
public override fun nextInt(): Int = generator.nextInt()
public override fun nextInt(n: Int): Int = generator.nextInt(n)
public override fun nextGaussian(): Double = TODO()
public override fun nextDouble(): Double = generator.nextDouble()
public override fun nextLong(): Long = generator.nextLong()
}

@ -13,8 +13,7 @@ import scientifik.kmath.structures.*
/**
* Streaming and buffer transformations
*/
object Transformations {
public object Transformations {
private fun Buffer<Complex>.toArray(): Array<org.apache.commons.math3.complex.Complex> =
Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) }
@ -32,35 +31,35 @@ object Transformations {
Complex(value.real, value.imaginary)
}
fun fourier(
public fun fourier(
normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD
): SuspendBufferTransform<Complex, Complex> = {
FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer()
}
fun realFourier(
public fun realFourier(
normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD
): SuspendBufferTransform<Double, Complex> = {
FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer()
}
fun sine(
public fun sine(
normalization: DstNormalization = DstNormalization.STANDARD_DST_I,
direction: TransformType = TransformType.FORWARD
): SuspendBufferTransform<Double, Double> = {
FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer()
}
fun cosine(
public fun cosine(
normalization: DctNormalization = DctNormalization.STANDARD_DCT_I,
direction: TransformType = TransformType.FORWARD
): SuspendBufferTransform<Double, Double> = {
FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer()
}
fun hadamard(
public fun hadamard(
direction: TransformType = TransformType.FORWARD
): SuspendBufferTransform<Double, Double> = {
FastHadamardTransformer().transform(it.asArray(), direction).asBuffer()
@ -71,7 +70,7 @@ object Transformations {
* Process given [Flow] with commons-math fft transformation
*/
@FlowPreview
fun Flow<Buffer<Complex>>.FFT(
public fun Flow<Buffer<Complex>>.FFT(
normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD
): Flow<Buffer<Complex>> {
@ -81,7 +80,7 @@ fun Flow<Buffer<Complex>>.FFT(
@FlowPreview
@JvmName("realFFT")
fun Flow<Buffer<Double>>.FFT(
public fun Flow<Buffer<Double>>.FFT(
normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD
): Flow<Buffer<Complex>> {
@ -90,20 +89,18 @@ fun Flow<Buffer<Double>>.FFT(
}
/**
* Process a continous flow of real numbers in FFT splitting it in chunks of [bufferSize].
* Process a continuous flow of real numbers in FFT splitting it in chunks of [bufferSize].
*/
@FlowPreview
@JvmName("realFFT")
fun Flow<Double>.FFT(
public fun Flow<Double>.FFT(
bufferSize: Int = Int.MAX_VALUE,
normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD
): Flow<Complex> {
return chunked(bufferSize).FFT(normalization,direction).spread()
}
): Flow<Complex> = chunked(bufferSize).FFT(normalization, direction).spread()
/**
* Map a complex flow into real flow by taking real part of each number
*/
@FlowPreview
fun Flow<Complex>.real(): Flow<Double> = map{it.re}
public fun Flow<Complex>.real(): Flow<Double> = map { it.re }

@ -6,12 +6,16 @@ import kotlin.contracts.contract
import kotlin.test.Test
import kotlin.test.assertEquals
inline fun <R> diff(order: Int, vararg parameters: Pair<String, Double>, block: DerivativeStructureField.() -> R): R {
internal inline fun <R> diff(
order: Int,
vararg parameters: Pair<String, Double>,
block: DerivativeStructureField.() -> R
): R {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return DerivativeStructureField(order, mapOf(*parameters)).run(block)
}
class AutoDiffTest {
internal class AutoDiffTest {
@Test
fun derivativeStructureFieldTest() {
val res = diff(3, "x" to 1.0, "y" to 1.0) {
@ -33,4 +37,4 @@ class AutoDiffTest {
assertEquals(10.0, f("x" to 1.0, "y" to 2.0))
assertEquals(6.0, f.derivative("x")("x" to 1.0, "y" to 2.0))
}
}
}

@ -1,11 +1,7 @@
plugins {
id("scientifik.mpp")
}
plugins { id("ru.mipt.npm.mpp") }
kotlin.sourceSets {
commonMain {
dependencies {
api(project(":kmath-memory"))
}
kotlin.sourceSets.commonMain {
dependencies {
api(project(":kmath-memory"))
}
}

@ -7,14 +7,14 @@ import scientifik.kmath.linear.Point
*
* @param T the type of element of this domain.
*/
interface Domain<T : Any> {
public interface Domain<T : Any> {
/**
* Checks if the specified point is contained in this domain.
*/
operator fun contains(point: Point<T>): Boolean
public operator fun contains(point: Point<T>): Boolean
/**
* Number of hyperspace dimensions.
*/
val dimension: Int
public val dimension: Int
}

@ -25,23 +25,22 @@ import scientifik.kmath.structures.indices
*
* @author Alexander Nozik
*/
class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBuffer) : RealDomain {
public class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBuffer) : RealDomain {
public override val dimension: Int get() = lower.size
override operator fun contains(point: Point<Double>): Boolean = point.indices.all { i ->
public override operator fun contains(point: Point<Double>): Boolean = point.indices.all { i ->
point[i] in lower[i]..upper[i]
}
override val dimension: Int get() = lower.size
public override fun getLowerBound(num: Int, point: Point<Double>): Double? = lower[num]
override fun getLowerBound(num: Int, point: Point<Double>): Double? = lower[num]
public override fun getLowerBound(num: Int): Double? = lower[num]
override fun getLowerBound(num: Int): Double? = lower[num]
public override fun getUpperBound(num: Int, point: Point<Double>): Double? = upper[num]
override fun getUpperBound(num: Int, point: Point<Double>): Double? = upper[num]
public override fun getUpperBound(num: Int): Double? = upper[num]
override fun getUpperBound(num: Int): Double? = upper[num]
override fun nearestInDomain(point: Point<Double>): Point<Double> {
public override fun nearestInDomain(point: Point<Double>): Point<Double> {
val res = DoubleArray(point.size) { i ->
when {
point[i] < lower[i] -> lower[i]
@ -53,16 +52,14 @@ class HyperSquareDomain(private val lower: RealBuffer, private val upper: RealBu
return RealBuffer(*res)
}
override fun volume(): Double {
public override fun volume(): Double {
var res = 1.0
for (i in 0 until dimension) {
if (lower[i].isInfinite() || upper[i].isInfinite()) {
return Double.POSITIVE_INFINITY
}
if (upper[i] > lower[i]) {
res *= upper[i] - lower[i]
}
if (lower[i].isInfinite() || upper[i].isInfinite()) return Double.POSITIVE_INFINITY
if (upper[i] > lower[i]) res *= upper[i] - lower[i]
}
return res
}
}

@ -22,8 +22,8 @@ import scientifik.kmath.linear.Point
*
* @author Alexander Nozik
*/
interface RealDomain : Domain<Double> {
fun nearestInDomain(point: Point<Double>): Point<Double>
public interface RealDomain : Domain<Double> {
public fun nearestInDomain(point: Point<Double>): Point<Double>
/**
* The lower edge for the domain going down from point
@ -31,7 +31,7 @@ interface RealDomain : Domain<Double> {
* @param point
* @return
*/
fun getLowerBound(num: Int, point: Point<Double>): Double?
public fun getLowerBound(num: Int, point: Point<Double>): Double?
/**
* The upper edge of the domain going up from point
@ -39,25 +39,25 @@ interface RealDomain : Domain<Double> {
* @param point
* @return
*/
fun getUpperBound(num: Int, point: Point<Double>): Double?
public fun getUpperBound(num: Int, point: Point<Double>): Double?
/**
* Global lower edge
* @param num
* @return
*/
fun getLowerBound(num: Int): Double?
public fun getLowerBound(num: Int): Double?
/**
* Global upper edge
* @param num
* @return
*/
fun getUpperBound(num: Int): Double?
public fun getUpperBound(num: Int): Double?
/**
* Hyper volume
* @return
*/
fun volume(): Double
public fun volume(): Double
}

@ -17,18 +17,18 @@ package scientifik.kmath.domains
import scientifik.kmath.linear.Point
class UnconstrainedDomain(override val dimension: Int) : RealDomain {
override operator fun contains(point: Point<Double>): Boolean = true
public class UnconstrainedDomain(public override val dimension: Int) : RealDomain {
public override operator fun contains(point: Point<Double>): Boolean = true
override fun getLowerBound(num: Int, point: Point<Double>): Double? = Double.NEGATIVE_INFINITY
public override fun getLowerBound(num: Int, point: Point<Double>): Double? = Double.NEGATIVE_INFINITY
override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY
public override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY
override fun getUpperBound(num: Int, point: Point<Double>): Double? = Double.POSITIVE_INFINITY
public override fun getUpperBound(num: Int, point: Point<Double>): Double? = Double.POSITIVE_INFINITY
override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY
public override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY
override fun nearestInDomain(point: Point<Double>): Point<Double> = point
public override fun nearestInDomain(point: Point<Double>): Point<Double> = point
override fun volume(): Double = Double.POSITIVE_INFINITY
public override fun volume(): Double = Double.POSITIVE_INFINITY
}

@ -3,17 +3,21 @@ package scientifik.kmath.domains
import scientifik.kmath.linear.Point
import scientifik.kmath.structures.asBuffer
inline class UnivariateDomain(val range: ClosedFloatingPointRange<Double>) : RealDomain {
operator fun contains(d: Double): Boolean = range.contains(d)
public inline class UnivariateDomain(public val range: ClosedFloatingPointRange<Double>) : RealDomain {
public override val dimension: Int
get() = 1
override operator fun contains(point: Point<Double>): Boolean {
public operator fun contains(d: Double): Boolean = range.contains(d)
public override operator fun contains(point: Point<Double>): Boolean {
require(point.size == 0)
return contains(point[0])
}
override fun nearestInDomain(point: Point<Double>): Point<Double> {
public override fun nearestInDomain(point: Point<Double>): Point<Double> {
require(point.size == 1)
val value = point[0]
return when {
value in range -> point
value >= range.endInclusive -> doubleArrayOf(range.endInclusive).asBuffer()
@ -21,27 +25,25 @@ inline class UnivariateDomain(val range: ClosedFloatingPointRange<Double>) : Rea
}
}
override fun getLowerBound(num: Int, point: Point<Double>): Double? {
public override fun getLowerBound(num: Int, point: Point<Double>): Double? {
require(num == 0)
return range.start
}
override fun getUpperBound(num: Int, point: Point<Double>): Double? {
public override fun getUpperBound(num: Int, point: Point<Double>): Double? {
require(num == 0)
return range.endInclusive
}
override fun getLowerBound(num: Int): Double? {
public override fun getLowerBound(num: Int): Double? {
require(num == 0)
return range.start
}
override fun getUpperBound(num: Int): Double? {
public override fun getUpperBound(num: Int): Double? {
require(num == 0)
return range.endInclusive
}
override fun volume(): Double = range.endInclusive - range.start
override val dimension: Int get() = 1
public override fun volume(): Double = range.endInclusive - range.start
}

@ -5,45 +5,37 @@ import scientifik.kmath.operations.Algebra
/**
* An elementary function that could be invoked on a map of arguments
*/
interface Expression<T> {
public fun interface Expression<T> {
/**
* Calls this expression from arguments.
*
* @param arguments the map of arguments.
* @return the value.
*/
operator fun invoke(arguments: Map<String, T>): T
public operator fun invoke(arguments: Map<String, T>): T
companion object
public companion object
}
/**
* Create simple lazily evaluated expression inside given algebra
*/
fun <T> Algebra<T>.expression(block: Algebra<T>.(arguments: Map<String, T>) -> T): Expression<T> =
object : Expression<T> {
override operator fun invoke(arguments: Map<String, T>): T = block(arguments)
}
/**
* Calls this expression from arguments.
*
* @param pairs the pair of arguments' names to values.
* @return the value.
*/
operator fun <T> Expression<T>.invoke(vararg pairs: Pair<String, T>): T = invoke(mapOf(*pairs))
public operator fun <T> Expression<T>.invoke(vararg pairs: Pair<String, T>): T = invoke(mapOf(*pairs))
/**
* A context for expression construction
*/
interface ExpressionAlgebra<T, E> : Algebra<E> {
public interface ExpressionAlgebra<T, E> : Algebra<E> {
/**
* Introduce a variable into expression context
*/
fun variable(name: String, default: T? = null): E
public fun variable(name: String, default: T? = null): E
/**
* A constant expression which does not depend on arguments
*/
fun const(value: T): E
public fun const(value: T): E
}

@ -4,7 +4,8 @@ import scientifik.kmath.operations.*
internal class FunctionalUnaryOperation<T>(val context: Algebra<T>, val name: String, private val expr: Expression<T>) :
Expression<T> {
override operator fun invoke(arguments: Map<String, T>): T = context.unaryOperation(name, expr.invoke(arguments))
public override operator fun invoke(arguments: Map<String, T>): T =
context.unaryOperation(name, expr.invoke(arguments))
}
internal class FunctionalBinaryOperation<T>(
@ -13,17 +14,17 @@ internal class FunctionalBinaryOperation<T>(
val first: Expression<T>,
val second: Expression<T>
) : Expression<T> {
override operator fun invoke(arguments: Map<String, T>): T =
public override operator fun invoke(arguments: Map<String, T>): T =
context.binaryOperation(name, first.invoke(arguments), second.invoke(arguments))
}
internal class FunctionalVariableExpression<T>(val name: String, val default: T? = null) : Expression<T> {
override operator fun invoke(arguments: Map<String, T>): T =
public override operator fun invoke(arguments: Map<String, T>): T =
arguments[name] ?: default ?: error("Parameter not found: $name")
}
internal class FunctionalConstantExpression<T>(val value: T) : Expression<T> {
override operator fun invoke(arguments: Map<String, T>): T = value
public override operator fun invoke(arguments: Map<String, T>): T = value
}
internal class FunctionalConstProductExpression<T>(
@ -31,7 +32,7 @@ internal class FunctionalConstProductExpression<T>(
private val expr: Expression<T>,
val const: Number
) : Expression<T> {
override operator fun invoke(arguments: Map<String, T>): T = context.multiply(expr.invoke(arguments), const)
public override operator fun invoke(arguments: Map<String, T>): T = context.multiply(expr.invoke(arguments), const)
}
/**
@ -39,131 +40,132 @@ internal class FunctionalConstProductExpression<T>(
*
* @param algebra The algebra to provide for Expressions built.
*/
abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(val algebra: A) : ExpressionAlgebra<T, Expression<T>> {
public abstract class FunctionalExpressionAlgebra<T, A : Algebra<T>>(public val algebra: A) :
ExpressionAlgebra<T, Expression<T>> {
/**
* Builds an Expression of constant expression which does not depend on arguments.
*/
override fun const(value: T): Expression<T> = FunctionalConstantExpression(value)
public override fun const(value: T): Expression<T> = FunctionalConstantExpression(value)
/**
* Builds an Expression to access a variable.
*/
override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
public override fun variable(name: String, default: T?): Expression<T> = FunctionalVariableExpression(name, default)
/**
* Builds an Expression of dynamic call of binary operation [operation] on [left] and [right].
*/
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
FunctionalBinaryOperation(algebra, operation, left, right)
/**
* Builds an Expression of dynamic call of unary operation with name [operation] on [arg].
*/
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
FunctionalUnaryOperation(algebra, operation, arg)
}
/**
* A context class for [Expression] construction for [Space] algebras.
*/
open class FunctionalExpressionSpace<T, A : Space<T>>(algebra: A) :
public open class FunctionalExpressionSpace<T, A : Space<T>>(algebra: A) :
FunctionalExpressionAlgebra<T, A>(algebra), Space<Expression<T>> {
override val zero: Expression<T> get() = const(algebra.zero)
public override val zero: Expression<T> get() = const(algebra.zero)
/**
* Builds an Expression of addition of two another expressions.
*/
override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
public override fun add(a: Expression<T>, b: Expression<T>): Expression<T> =
binaryOperation(SpaceOperations.PLUS_OPERATION, a, b)
/**
* Builds an Expression of multiplication of expression by number.
*/
override fun multiply(a: Expression<T>, k: Number): Expression<T> =
public override fun multiply(a: Expression<T>, k: Number): Expression<T> =
FunctionalConstProductExpression(algebra, a, k)
operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
operator fun Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
operator fun T.plus(arg: Expression<T>): Expression<T> = arg + this
operator fun T.minus(arg: Expression<T>): Expression<T> = arg - this
public operator fun Expression<T>.plus(arg: T): Expression<T> = this + const(arg)
public operator fun Expression<T>.minus(arg: T): Expression<T> = this - const(arg)
public operator fun T.plus(arg: Expression<T>): Expression<T> = arg + this
public operator fun T.minus(arg: Expression<T>): Expression<T> = arg - this
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionAlgebra>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionAlgebra>.binaryOperation(operation, left, right)
}
open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
public open class FunctionalExpressionRing<T, A>(algebra: A) : FunctionalExpressionSpace<T, A>(algebra),
Ring<Expression<T>> where A : Ring<T>, A : NumericAlgebra<T> {
override val one: Expression<T>
public override val one: Expression<T>
get() = const(algebra.one)
/**
* Builds an Expression of multiplication of two expressions.
*/
override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> =
public override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> =
binaryOperation(RingOperations.TIMES_OPERATION, a, b)
operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
public operator fun Expression<T>.times(arg: T): Expression<T> = this * const(arg)
public operator fun T.times(arg: Expression<T>): Expression<T> = arg * this
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionSpace>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionSpace>.binaryOperation(operation, left, right)
}
open class FunctionalExpressionField<T, A>(algebra: A) :
public open class FunctionalExpressionField<T, A>(algebra: A) :
FunctionalExpressionRing<T, A>(algebra),
Field<Expression<T>> where A : Field<T>, A : NumericAlgebra<T> {
/**
* Builds an Expression of division an expression by another one.
*/
override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> =
public override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> =
binaryOperation(FieldOperations.DIV_OPERATION, a, b)
operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
public operator fun Expression<T>.div(arg: T): Expression<T> = this / const(arg)
public operator fun T.div(arg: Expression<T>): Expression<T> = arg / this
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionRing>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionRing>.binaryOperation(operation, left, right)
}
open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
public open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
FunctionalExpressionField<T, A>(algebra),
ExtendedField<Expression<T>> where A : ExtendedField<T>, A : NumericAlgebra<T> {
override fun sin(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
override fun cos(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
override fun asin(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
override fun acos(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
override fun atan(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
public override fun sin(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
public override fun cos(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
public override fun asin(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
public override fun acos(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
public override fun atan(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
override fun power(arg: Expression<T>, pow: Number): Expression<T> =
public override fun power(arg: Expression<T>, pow: Number): Expression<T> =
binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow))
override fun exp(arg: Expression<T>): Expression<T> = unaryOperation(ExponentialOperations.EXP_OPERATION, arg)
override fun ln(arg: Expression<T>): Expression<T> = unaryOperation(ExponentialOperations.LN_OPERATION, arg)
public override fun exp(arg: Expression<T>): Expression<T> = unaryOperation(ExponentialOperations.EXP_OPERATION, arg)
public override fun ln(arg: Expression<T>): Expression<T> = unaryOperation(ExponentialOperations.LN_OPERATION, arg)
override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
public override fun unaryOperation(operation: String, arg: Expression<T>): Expression<T> =
super<FunctionalExpressionField>.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
public override fun binaryOperation(operation: String, left: Expression<T>, right: Expression<T>): Expression<T> =
super<FunctionalExpressionField>.binaryOperation(operation, left, right)
}
inline fun <T, A : Space<T>> A.expressionInSpace(block: FunctionalExpressionSpace<T, A>.() -> Expression<T>): Expression<T> =
public inline fun <T, A : Space<T>> A.expressionInSpace(block: FunctionalExpressionSpace<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionSpace(this).block()
inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressionRing<T, A>.() -> Expression<T>): Expression<T> =
public inline fun <T, A : Ring<T>> A.expressionInRing(block: FunctionalExpressionRing<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionRing(this).block()
inline fun <T, A : Field<T>> A.expressionInField(block: FunctionalExpressionField<T, A>.() -> Expression<T>): Expression<T> =
public inline fun <T, A : Field<T>> A.expressionInField(block: FunctionalExpressionField<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionField(this).block()
inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>): Expression<T> =
public inline fun <T, A : ExtendedField<T>> A.expressionInExtendedField(block: FunctionalExpressionExtendedField<T, A>.() -> Expression<T>): Expression<T> =
FunctionalExpressionExtendedField(this).block()

@ -11,7 +11,7 @@ import kotlin.contracts.contract
/**
* Creates a functional expression with this [Space].
*/
inline fun <T> Space<T>.spaceExpression(block: FunctionalExpressionSpace<T, Space<T>>.() -> Expression<T>): Expression<T> {
public inline fun <T> Space<T>.spaceExpression(block: FunctionalExpressionSpace<T, Space<T>>.() -> Expression<T>): Expression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return FunctionalExpressionSpace(this).block()
}
@ -19,7 +19,7 @@ inline fun <T> Space<T>.spaceExpression(block: FunctionalExpressionSpace<T, Spac
/**
* Creates a functional expression with this [Ring].
*/
inline fun <T> Ring<T>.ringExpression(block: FunctionalExpressionRing<T, Ring<T>>.() -> Expression<T>): Expression<T> {
public inline fun <T> Ring<T>.ringExpression(block: FunctionalExpressionRing<T, Ring<T>>.() -> Expression<T>): Expression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return FunctionalExpressionRing(this).block()
}
@ -27,7 +27,7 @@ inline fun <T> Ring<T>.ringExpression(block: FunctionalExpressionRing<T, Ring<T>
/**
* Creates a functional expression with this [Field].
*/
inline fun <T> Field<T>.fieldExpression(block: FunctionalExpressionField<T, Field<T>>.() -> Expression<T>): Expression<T> {
public inline fun <T> Field<T>.fieldExpression(block: FunctionalExpressionField<T, Field<T>>.() -> Expression<T>): Expression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return FunctionalExpressionField(this).block()
}
@ -35,7 +35,7 @@ inline fun <T> Field<T>.fieldExpression(block: FunctionalExpressionField<T, Fiel
/**
* Creates a functional expression with this [ExtendedField].
*/
inline fun <T> ExtendedField<T>.extendedFieldExpression(block: FunctionalExpressionExtendedField<T, ExtendedField<T>>.() -> Expression<T>): Expression<T> {
public inline fun <T> ExtendedField<T>.extendedFieldExpression(block: FunctionalExpressionExtendedField<T, ExtendedField<T>>.() -> Expression<T>): Expression<T> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return FunctionalExpressionExtendedField(this).block()
}

@ -7,111 +7,106 @@ import scientifik.kmath.structures.*
/**
* Basic implementation of Matrix space based on [NDStructure]
*/
class BufferMatrixContext<T : Any, R : Ring<T>>(
override val elementContext: R,
public class BufferMatrixContext<T : Any, R : Ring<T>>(
public override val elementContext: R,
private val bufferFactory: BufferFactory<T>
) : GenericMatrixContext<T, R> {
override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix<T> {
public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): BufferMatrix<T> {
val buffer = bufferFactory(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
return BufferMatrix(rows, columns, buffer)
}
override fun point(size: Int, initializer: (Int) -> T): Point<T> = bufferFactory(size, initializer)
public override fun point(size: Int, initializer: (Int) -> T): Point<T> = bufferFactory(size, initializer)
companion object
public companion object
}
@Suppress("OVERRIDE_BY_INLINE")
object RealMatrixContext : GenericMatrixContext<Double, RealField> {
public object RealMatrixContext : GenericMatrixContext<Double, RealField> {
public override val elementContext: RealField
get() = RealField
override val elementContext: RealField get() = RealField
override inline fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): Matrix<Double> {
public override inline fun produce(
rows: Int,
columns: Int,
initializer: (i: Int, j: Int) -> Double
): Matrix<Double> {
val buffer = RealBuffer(rows * columns) { offset -> initializer(offset / columns, offset % columns) }
return BufferMatrix(rows, columns, buffer)
}
override inline fun point(size: Int, initializer: (Int) -> Double): Point<Double> = RealBuffer(size, initializer)
public override inline fun point(size: Int, initializer: (Int) -> Double): Point<Double> =
RealBuffer(size, initializer)
}
class BufferMatrix<T : Any>(
override val rowNum: Int,
override val colNum: Int,
val buffer: Buffer<out T>,
override val features: Set<MatrixFeature> = emptySet()
public class BufferMatrix<T : Any>(
public override val rowNum: Int,
public override val colNum: Int,
public val buffer: Buffer<out T>,
public override val features: Set<MatrixFeature> = emptySet()
) : FeaturedMatrix<T> {
override val shape: IntArray
get() = intArrayOf(rowNum, colNum)
init {
if (buffer.size != rowNum * colNum) {
error("Dimension mismatch for matrix structure")
}
require(buffer.size == rowNum * colNum) { "Dimension mismatch for matrix structure" }
}
override val shape: IntArray get() = intArrayOf(rowNum, colNum)
override fun suggestFeature(vararg features: MatrixFeature): BufferMatrix<T> =
public override fun suggestFeature(vararg features: MatrixFeature): BufferMatrix<T> =
BufferMatrix(rowNum, colNum, buffer, this.features + features)
override operator fun get(index: IntArray): T = get(index[0], index[1])
public override operator fun get(index: IntArray): T = get(index[0], index[1])
public override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j]
override operator fun get(i: Int, j: Int): T = buffer[i * colNum + j]
override fun elements(): Sequence<Pair<IntArray, T>> = sequence {
public override fun elements(): Sequence<Pair<IntArray, T>> = sequence {
for (i in 0 until rowNum) for (j in 0 until colNum) yield(intArrayOf(i, j) to get(i, j))
}
override fun equals(other: Any?): Boolean {
public override fun equals(other: Any?): Boolean {
if (this === other) return true
return when (other) {
is NDStructure<*> -> return NDStructure.equals(this, other)
else -> false
}
}
override fun hashCode(): Int {
public override fun hashCode(): Int {
var result = buffer.hashCode()
result = 31 * result + features.hashCode()
return result
}
override fun toString(): String {
return if (rowNum <= 5 && colNum <= 5) {
public override fun toString(): String {
return if (rowNum <= 5 && colNum <= 5)
"Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)\n" +
rows.asSequence().joinToString(prefix = "(", postfix = ")", separator = "\n ") { buffer ->
buffer.asSequence().joinToString(separator = "\t") { it.toString() }
}
} else {
"Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)"
}
else "Matrix(rowsNum = $rowNum, colNum = $colNum, features=$features)"
}
}
/**
* Optimized dot product for real matrices
*/
infix fun BufferMatrix<Double>.dot(other: BufferMatrix<Double>): BufferMatrix<Double> {
public infix fun BufferMatrix<Double>.dot(other: BufferMatrix<Double>): BufferMatrix<Double> {
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
val array = DoubleArray(this.rowNum * other.colNum)
//convert to array to insure there is not memory indirection
fun Buffer<out Double>.unsafeArray(): DoubleArray = if (this is RealBuffer) {
fun Buffer<out Double>.unsafeArray() = if (this is RealBuffer)
array
} else {
else
DoubleArray(size) { get(it) }
}
val a = this.buffer.unsafeArray()
val b = other.buffer.unsafeArray()
for (i in (0 until rowNum)) {
for (j in (0 until other.colNum)) {
for (k in (0 until colNum)) {
for (i in (0 until rowNum))
for (j in (0 until other.colNum))
for (k in (0 until colNum))
array[i * other.colNum + j] += a[i * colNum + k] * b[k * other.colNum + j]
}
}
}
val buffer = RealBuffer(array)
return BufferMatrix(rowNum, other.colNum, buffer)

@ -11,11 +11,9 @@ import kotlin.math.sqrt
/**
* A 2d structure plus optional matrix-specific features
*/
interface FeaturedMatrix<T : Any> : Matrix<T> {
public interface FeaturedMatrix<T : Any> : Matrix<T> {
override val shape: IntArray get() = intArrayOf(rowNum, colNum)
val features: Set<MatrixFeature>
public val features: Set<MatrixFeature>
/**
* Suggest new feature for this matrix. The result is the new matrix that may or may not reuse existing data structure.
@ -23,44 +21,42 @@ interface FeaturedMatrix<T : Any> : Matrix<T> {
* The implementation does not guarantee to check that matrix actually have the feature, so one should be careful to
* add only those features that are valid.
*/
fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix<T>
public fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix<T>
companion object
public companion object
}
inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix<Double> {
contract { callsInPlace(initializer) }
return MatrixContext.real.produce(rows, columns, initializer)
}
public inline fun Structure2D.Companion.real(rows: Int, columns: Int, initializer: (Int, Int) -> Double): Matrix<Double> =
MatrixContext.real.produce(rows, columns, initializer)
/**
* Build a square matrix from given elements.
*/
fun <T : Any> Structure2D.Companion.square(vararg elements: T): FeaturedMatrix<T> {
public fun <T : Any> Structure2D.Companion.square(vararg elements: T): FeaturedMatrix<T> {
val size: Int = sqrt(elements.size.toDouble()).toInt()
require(size * size == elements.size) { "The number of elements ${elements.size} is not a full square" }
val buffer = elements.asBuffer()
return BufferMatrix(size, size, buffer)
}
val Matrix<*>.features: Set<MatrixFeature> get() = (this as? FeaturedMatrix)?.features ?: emptySet()
public val Matrix<*>.features: Set<MatrixFeature> get() = (this as? FeaturedMatrix)?.features ?: emptySet()
/**
* Check if matrix has the given feature class
*/
inline fun <reified T : Any> Matrix<*>.hasFeature(): Boolean =
public inline fun <reified T : Any> Matrix<*>.hasFeature(): Boolean =
features.find { it is T } != null
/**
* Get the first feature matching given class. Does not guarantee that matrix has only one feature matching the criteria
*/
inline fun <reified T : Any> Matrix<*>.getFeature(): T? =
public inline fun <reified T : Any> Matrix<*>.getFeature(): T? =
features.filterIsInstance<T>().firstOrNull()
/**
* Diagonal matrix of ones. The matrix is virtual no actual matrix is created
*/
fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R>.one(rows: Int, columns: Int): FeaturedMatrix<T> =
public fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R>.one(rows: Int, columns: Int): FeaturedMatrix<T> =
VirtualMatrix(rows, columns, DiagonalFeature) { i, j ->
if (i == j) elementContext.one else elementContext.zero
}
@ -69,20 +65,20 @@ fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R>.one(rows: Int, columns: In
/**
* A virtual matrix of zeroes
*/
fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R>.zero(rows: Int, columns: Int): FeaturedMatrix<T> =
public fun <T : Any, R : Ring<T>> GenericMatrixContext<T, R>.zero(rows: Int, columns: Int): FeaturedMatrix<T> =
VirtualMatrix(rows, columns) { _, _ -> elementContext.zero }
class TransposedFeature<T : Any>(val original: Matrix<T>) : MatrixFeature
public class TransposedFeature<T : Any>(public val original: Matrix<T>) : MatrixFeature
/**
* Create a virtual transposed matrix without copying anything. `A.transpose().transpose() === A`
*/
fun <T : Any> Matrix<T>.transpose(): Matrix<T> {
return this.getFeature<TransposedFeature<T>>()?.original ?: VirtualMatrix(
this.colNum,
this.rowNum,
public fun <T : Any> Matrix<T>.transpose(): Matrix<T> {
return getFeature<TransposedFeature<T>>()?.original ?: VirtualMatrix(
colNum,
rowNum,
setOf(TransposedFeature(this))
) { i, j -> get(j, i) }
}
infix fun Matrix<Double>.dot(other: Matrix<Double>): Matrix<Double> = with(MatrixContext.real) { dot(other) }
public infix fun Matrix<Double>.dot(other: Matrix<Double>): Matrix<Double> = with(MatrixContext.real) { dot(other) }

@ -7,19 +7,20 @@ import scientifik.kmath.operations.invoke
import scientifik.kmath.structures.BufferAccessor2D
import scientifik.kmath.structures.Matrix
import scientifik.kmath.structures.Structure2D
import kotlin.contracts.contract
import kotlin.reflect.KClass
/**
* Common implementation of [LUPDecompositionFeature]
*/
class LUPDecomposition<T : Any>(
val context: GenericMatrixContext<T, out Field<T>>,
val lu: Structure2D<T>,
val pivot: IntArray,
public class LUPDecomposition<T : Any>(
public val context: GenericMatrixContext<T, out Field<T>>,
public val lu: Structure2D<T>,
public val pivot: IntArray,
private val even: Boolean
) : LUPDecompositionFeature<T>, DeterminantFeature<T> {
val elementContext: Field<T> get() = context.elementContext
public val elementContext: Field<T>
get() = context.elementContext
/**
* Returns the matrix L of the decomposition.
@ -44,7 +45,6 @@ class LUPDecomposition<T : Any>(
if (j >= i) lu[i, j] else elementContext.zero
}
/**
* Returns the P rows permutation matrix.
*
@ -55,7 +55,6 @@ class LUPDecomposition<T : Any>(
if (j == pivot[i]) elementContext.one else elementContext.zero
}
/**
* Return the determinant of the matrix
* @return determinant of the matrix
@ -66,22 +65,18 @@ class LUPDecomposition<T : Any>(
}
fun <T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.abs(value: T): T =
public fun <T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.abs(value: T): T =
if (value > elementContext.zero) value else elementContext { -value }
/**
* Create a lup decomposition of generic matrix
*/
fun <T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.lup(
public inline fun <T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.lup(
type: KClass<T>,
matrix: Matrix<T>,
checkSingular: (T) -> Boolean
): LUPDecomposition<T> {
if (matrix.rowNum != matrix.colNum) {
error("LU decomposition supports only square matrices")
}
require(matrix.rowNum == matrix.colNum) { "LU decomposition supports only square matrices" }
val m = matrix.colNum
val pivot = IntArray(matrix.rowNum)
@ -154,15 +149,15 @@ fun <T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.lup(
}
}
inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.lup(
public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.lup(
matrix: Matrix<T>,
noinline checkSingular: (T) -> Boolean
checkSingular: (T) -> Boolean
): LUPDecomposition<T> = lup(T::class, matrix, checkSingular)
fun GenericMatrixContext<Double, RealField>.lup(matrix: Matrix<Double>): LUPDecomposition<Double> =
public fun GenericMatrixContext<Double, RealField>.lup(matrix: Matrix<Double>): LUPDecomposition<Double> =
lup(Double::class, matrix) { it < 1e-11 }
fun <T : Any> LUPDecomposition<T>.solve(type: KClass<T>, matrix: Matrix<T>): Matrix<T> {
public fun <T : Any> LUPDecomposition<T>.solve(type: KClass<T>, matrix: Matrix<T>): Matrix<T> {
require(matrix.rowNum == pivot.size) { "Matrix dimension mismatch. Expected ${pivot.size}, but got ${matrix.colNum}" }
BufferAccessor2D(type, matrix.rowNum, matrix.colNum).run {
@ -207,27 +202,27 @@ fun <T : Any> LUPDecomposition<T>.solve(type: KClass<T>, matrix: Matrix<T>): Mat
}
}
inline fun <reified T : Any> LUPDecomposition<T>.solve(matrix: Matrix<T>): Matrix<T> = solve(T::class, matrix)
public inline fun <reified T : Any> LUPDecomposition<T>.solve(matrix: Matrix<T>): Matrix<T> = solve(T::class, matrix)
/**
* Solve a linear equation **a*x = b**
*/
inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.solve(
public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.solve(
a: Matrix<T>,
b: Matrix<T>,
noinline checkSingular: (T) -> Boolean
checkSingular: (T) -> Boolean
): Matrix<T> {
// Use existing decomposition if it is provided by matrix
val decomposition = a.getFeature() ?: lup(T::class, a, checkSingular)
return decomposition.solve(T::class, b)
}
fun RealMatrixContext.solve(a: Matrix<Double>, b: Matrix<Double>): Matrix<Double> = solve(a, b) { it < 1e-11 }
public fun RealMatrixContext.solve(a: Matrix<Double>, b: Matrix<Double>): Matrix<Double> = solve(a, b) { it < 1e-11 }
inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.inverse(
public inline fun <reified T : Comparable<T>, F : Field<T>> GenericMatrixContext<T, F>.inverse(
matrix: Matrix<T>,
noinline checkSingular: (T) -> Boolean
checkSingular: (T) -> Boolean
): Matrix<T> = solve(matrix, one(matrix.rowNum, matrix.colNum), checkSingular)
fun RealMatrixContext.inverse(matrix: Matrix<Double>): Matrix<Double> =
public fun RealMatrixContext.inverse(matrix: Matrix<Double>): Matrix<Double> =
solve(matrix, one(matrix.rowNum, matrix.colNum)) { it < 1e-11 }

@ -4,25 +4,24 @@ import scientifik.kmath.structures.Buffer
import scientifik.kmath.structures.Matrix
import scientifik.kmath.structures.VirtualBuffer
typealias Point<T> = Buffer<T>
public typealias Point<T> = Buffer<T>
/**
* A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors
*/
interface LinearSolver<T : Any> {
fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T>
fun solve(a: Matrix<T>, b: Point<T>): Point<T> = solve(a, b.asMatrix()).asPoint()
fun inverse(a: Matrix<T>): Matrix<T>
public interface LinearSolver<T : Any> {
public fun solve(a: Matrix<T>, b: Matrix<T>): Matrix<T>
public fun solve(a: Matrix<T>, b: Point<T>): Point<T> = solve(a, b.asMatrix()).asPoint()
public fun inverse(a: Matrix<T>): Matrix<T>
}
/**
* Convert matrix to vector if it is possible
*/
fun <T : Any> Matrix<T>.asPoint(): Point<T> =
if (this.colNum == 1) {
public fun <T : Any> Matrix<T>.asPoint(): Point<T> =
if (this.colNum == 1)
VirtualBuffer(rowNum) { get(it, 0) }
} else {
else
error("Can't convert matrix with more than one column to vector")
}
fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(size, 1) { i, _ -> get(i) }
public fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(size, 1) { i, _ -> get(i) }

@ -5,8 +5,8 @@ import scientifik.kmath.structures.BufferFactory
import scientifik.kmath.structures.Structure2D
import scientifik.kmath.structures.asBuffer
class MatrixBuilder(val rows: Int, val columns: Int) {
operator fun <T : Any> invoke(vararg elements: T): FeaturedMatrix<T> {
public class MatrixBuilder(public val rows: Int, public val columns: Int) {
public operator fun <T : Any> invoke(vararg elements: T): FeaturedMatrix<T> {
require(rows * columns == elements.size) { "The number of elements ${elements.size} is not equal $rows * $columns" }
val buffer = elements.asBuffer()
return BufferMatrix(rows, columns, buffer)
@ -15,14 +15,14 @@ class MatrixBuilder(val rows: Int, val columns: Int) {
//TODO add specific matrix builder functions like diagonal, etc
}
fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns)
public fun Structure2D.Companion.build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns)
fun <T : Any> Structure2D.Companion.row(vararg values: T): FeaturedMatrix<T> {
public fun <T : Any> Structure2D.Companion.row(vararg values: T): FeaturedMatrix<T> {
val buffer = values.asBuffer()
return BufferMatrix(1, values.size, buffer)
}
inline fun <reified T : Any> Structure2D.Companion.row(
public inline fun <reified T : Any> Structure2D.Companion.row(
size: Int,
factory: BufferFactory<T> = Buffer.Companion::auto,
noinline builder: (Int) -> T
@ -31,12 +31,12 @@ inline fun <reified T : Any> Structure2D.Companion.row(
return BufferMatrix(1, size, buffer)
}
fun <T : Any> Structure2D.Companion.column(vararg values: T): FeaturedMatrix<T> {
public fun <T : Any> Structure2D.Companion.column(vararg values: T): FeaturedMatrix<T> {
val buffer = values.asBuffer()
return BufferMatrix(values.size, 1, buffer)
}
inline fun <reified T : Any> Structure2D.Companion.column(
public inline fun <reified T : Any> Structure2D.Companion.column(
size: Int,
factory: BufferFactory<T> = Buffer.Companion::auto,
noinline builder: (Int) -> T

@ -12,30 +12,31 @@ import scientifik.kmath.structures.asSequence
/**
* Basic operations on matrices. Operates on [Matrix]
*/
interface MatrixContext<T : Any> : SpaceOperations<Matrix<T>> {
public interface MatrixContext<T : Any> : SpaceOperations<Matrix<T>> {
/**
* Produce a matrix with this context and given dimensions
*/
fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix<T>
public fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): Matrix<T>
infix fun Matrix<T>.dot(other: Matrix<T>): Matrix<T>
public infix fun Matrix<T>.dot(other: Matrix<T>): Matrix<T>
infix fun Matrix<T>.dot(vector: Point<T>): Point<T>
public infix fun Matrix<T>.dot(vector: Point<T>): Point<T>
operator fun Matrix<T>.times(value: T): Matrix<T>
public operator fun Matrix<T>.times(value: T): Matrix<T>
operator fun T.times(m: Matrix<T>): Matrix<T> = m * this
public operator fun T.times(m: Matrix<T>): Matrix<T> = m * this
companion object {
public companion object {
/**
* Non-boxing double matrix
*/
val real: RealMatrixContext = RealMatrixContext
public val real: RealMatrixContext
get() = RealMatrixContext
/**
* A structured matrix with custom buffer
*/
fun <T : Any, R : Ring<T>> buffered(
public fun <T : Any, R : Ring<T>> buffered(
ring: R,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
): GenericMatrixContext<T, R> = BufferMatrixContext(ring, bufferFactory)
@ -43,21 +44,21 @@ interface MatrixContext<T : Any> : SpaceOperations<Matrix<T>> {
/**
* Automatic buffered matrix, unboxed if it is possible
*/
inline fun <reified T : Any, R : Ring<T>> auto(ring: R): GenericMatrixContext<T, R> =
public inline fun <reified T : Any, R : Ring<T>> auto(ring: R): GenericMatrixContext<T, R> =
buffered(ring, Buffer.Companion::auto)
}
}
interface GenericMatrixContext<T : Any, R : Ring<T>> : MatrixContext<T> {
public interface GenericMatrixContext<T : Any, R : Ring<T>> : MatrixContext<T> {
/**
* The ring context for matrix elements
*/
val elementContext: R
public val elementContext: R
/**
* Produce a point compatible with matrix space
*/
fun point(size: Int, initializer: (Int) -> T): Point<T>
public fun point(size: Int, initializer: (Int) -> T): Point<T>
override infix fun Matrix<T>.dot(other: Matrix<T>): Matrix<T> {
//TODO add typed error
@ -102,7 +103,7 @@ interface GenericMatrixContext<T : Any, R : Ring<T>> : MatrixContext<T> {
override fun multiply(a: Matrix<T>, k: Number): Matrix<T> =
produce(a.rowNum, a.colNum) { i, j -> elementContext { a[i, j] * k } }
operator fun Number.times(matrix: FeaturedMatrix<T>): Matrix<T> = matrix * this
public operator fun Number.times(matrix: FeaturedMatrix<T>): Matrix<T> = matrix * this
override operator fun Matrix<T>.times(value: T): Matrix<T> =
produce(rowNum, colNum) { i, j -> elementContext { get(i, j) * value } }

@ -4,59 +4,59 @@ package scientifik.kmath.linear
* A marker interface representing some matrix feature like diagonal, sparse, zero, etc. Features used to optimize matrix
* operations performance in some cases.
*/
interface MatrixFeature
public interface MatrixFeature
/**
* The matrix with this feature is considered to have only diagonal non-null elements
*/
object DiagonalFeature : MatrixFeature
public object DiagonalFeature : MatrixFeature
/**
* Matrix with this feature has all zero elements
*/
object ZeroFeature : MatrixFeature
public object ZeroFeature : MatrixFeature
/**
* Matrix with this feature have unit elements on diagonal and zero elements in all other places
*/
object UnitFeature : MatrixFeature
public object UnitFeature : MatrixFeature
/**
* Inverted matrix feature
*/
interface InverseMatrixFeature<T : Any> : MatrixFeature {
val inverse: FeaturedMatrix<T>
public interface InverseMatrixFeature<T : Any> : MatrixFeature {
public val inverse: FeaturedMatrix<T>
}
/**
* A determinant container
*/
interface DeterminantFeature<T : Any> : MatrixFeature {
val determinant: T
public interface DeterminantFeature<T : Any> : MatrixFeature {
public val determinant: T
}
@Suppress("FunctionName")
fun <T : Any> DeterminantFeature(determinant: T): DeterminantFeature<T> = object : DeterminantFeature<T> {
public fun <T : Any> DeterminantFeature(determinant: T): DeterminantFeature<T> = object : DeterminantFeature<T> {
override val determinant: T = determinant
}
/**
* Lower triangular matrix
*/
object LFeature : MatrixFeature
public object LFeature : MatrixFeature
/**
* Upper triangular feature
*/
object UFeature : MatrixFeature
public object UFeature : MatrixFeature
/**
* TODO add documentation
*/
interface LUPDecompositionFeature<T : Any> : MatrixFeature {
val l: FeaturedMatrix<T>
val u: FeaturedMatrix<T>
val p: FeaturedMatrix<T>
public interface LUPDecompositionFeature<T : Any> : MatrixFeature {
public val l: FeaturedMatrix<T>
public val u: FeaturedMatrix<T>
public val p: FeaturedMatrix<T>
}
//TODO add sparse matrix feature

@ -10,12 +10,12 @@ import scientifik.kmath.structures.BufferFactory
* A linear space for vectors.
* Could be used on any point-like structure
*/
interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
val size: Int
val space: S
public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
public val size: Int
public val space: S
override val zero: Point<T> get() = produce { space.zero }
fun produce(initializer: (Int) -> T): Point<T>
public fun produce(initializer: (Int) -> T): Point<T>
/**
* Produce a space-element of this vector space for expressions
@ -28,13 +28,13 @@ interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
//TODO add basis
companion object {
public companion object {
private val realSpaceCache: MutableMap<Int, BufferVectorSpace<Double, RealField>> = hashMapOf()
/**
* Non-boxing double vector space
*/
fun real(size: Int): BufferVectorSpace<Double, RealField> = realSpaceCache.getOrPut(size) {
public fun real(size: Int): BufferVectorSpace<Double, RealField> = realSpaceCache.getOrPut(size) {
BufferVectorSpace(
size,
RealField,
@ -45,7 +45,7 @@ interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
/**
* A structured vector space with custom buffer
*/
fun <T : Any, S : Space<T>> buffered(
public fun <T : Any, S : Space<T>> buffered(
size: Int,
space: S,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
@ -54,16 +54,16 @@ interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
/**
* Automatic buffered vector, unboxed if it is possible
*/
inline fun <reified T : Any, S : Space<T>> auto(size: Int, space: S): VectorSpace<T, S> =
public inline fun <reified T : Any, S : Space<T>> auto(size: Int, space: S): VectorSpace<T, S> =
buffered(size, space, Buffer.Companion::auto)
}
}
class BufferVectorSpace<T : Any, S : Space<T>>(
public class BufferVectorSpace<T : Any, S : Space<T>>(
override val size: Int,
override val space: S,
val bufferFactory: BufferFactory<T>
public val bufferFactory: BufferFactory<T>
) : VectorSpace<T, S> {
override fun produce(initializer: (Int) -> T): Buffer<T> = bufferFactory(size, initializer)
//override fun produceElement(initializer: (Int) -> T): Vector<T, S> = BufferVector(this, produce(initializer))

@ -2,14 +2,18 @@ package scientifik.kmath.linear
import scientifik.kmath.structures.Matrix
class VirtualMatrix<T : Any>(
public class VirtualMatrix<T : Any>(
override val rowNum: Int,
override val colNum: Int,
override val features: Set<MatrixFeature> = emptySet(),
val generator: (i: Int, j: Int) -> T
public val generator: (i: Int, j: Int) -> T
) : FeaturedMatrix<T> {
constructor(rowNum: Int, colNum: Int, vararg features: MatrixFeature, generator: (i: Int, j: Int) -> T) : this(
public constructor(
rowNum: Int,
colNum: Int,
vararg features: MatrixFeature,
generator: (i: Int, j: Int) -> T
) : this(
rowNum,
colNum,
setOf(*features),
@ -42,18 +46,15 @@ class VirtualMatrix<T : Any>(
}
companion object {
public companion object {
/**
* Wrap a matrix adding additional features to it
*/
fun <T : Any> wrap(matrix: Matrix<T>, vararg features: MatrixFeature): FeaturedMatrix<T> {
return if (matrix is VirtualMatrix) {
public fun <T : Any> wrap(matrix: Matrix<T>, vararg features: MatrixFeature): FeaturedMatrix<T> {
return if (matrix is VirtualMatrix)
VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features, matrix.generator)
} else {
VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features) { i, j ->
matrix[i, j]
}
}
else
VirtualMatrix(matrix.rowNum, matrix.colNum, matrix.features + features) { i, j -> matrix[i, j] }
}
}
}

@ -19,24 +19,24 @@ import kotlin.contracts.contract
* Differentiable variable with value and derivative of differentiation ([deriv]) result
* with respect to this variable.
*/
open class Variable<T : Any>(val value: T)
public open class Variable<T : Any>(public val value: T)
class DerivationResult<T : Any>(
public class DerivationResult<T : Any>(
value: T,
val deriv: Map<Variable<T>, T>,
val context: Field<T>
public val deriv: Map<Variable<T>, T>,
public val context: Field<T>
) : Variable<T>(value) {
fun deriv(variable: Variable<T>): T = deriv[variable] ?: context.zero
public fun deriv(variable: Variable<T>): T = deriv[variable] ?: context.zero
/**
* compute divergence
*/
fun div(): T = context { sum(deriv.values) }
public fun div(): T = context { sum(deriv.values) }
/**
* Compute a gradient for variables in given order
*/
fun grad(vararg variables: Variable<T>): Point<T> {
public fun grad(vararg variables: Variable<T>): Point<T> {
check(variables.isNotEmpty()) { "Variable order is not provided for gradient construction" }
return variables.map(::deriv).asBuffer()
}
@ -55,7 +55,7 @@ class DerivationResult<T : Any>(
* assertEquals(9.0, x.d) // dy/dx
* ```
*/
inline fun <T : Any, F : Field<T>> F.deriv(body: AutoDiffField<T, F>.() -> Variable<T>): DerivationResult<T> {
public inline fun <T : Any, F : Field<T>> F.deriv(body: AutoDiffField<T, F>.() -> Variable<T>): DerivationResult<T> {
contract { callsInPlace(body, InvocationKind.EXACTLY_ONCE) }
return (AutoDiffContext(this)) {
@ -67,14 +67,14 @@ inline fun <T : Any, F : Field<T>> F.deriv(body: AutoDiffField<T, F>.() -> Varia
}
abstract class AutoDiffField<T : Any, F : Field<T>> : Field<Variable<T>> {
abstract val context: F
public abstract class AutoDiffField<T : Any, F : Field<T>> : Field<Variable<T>> {
public abstract val context: F
/**
* A variable accessing inner state of derivatives.
* Use this function in inner builders to avoid creating additional derivative bindings
*/
abstract var Variable<T>.d: T
public abstract var Variable<T>.d: T
/**
* Performs update of derivative after the rest of the formula in the back-pass.
@ -87,11 +87,11 @@ abstract class AutoDiffField<T : Any, F : Field<T>> : Field<Variable<T>> {
* }
* ```
*/
abstract fun <R> derive(value: R, block: F.(R) -> Unit): R
public abstract fun <R> derive(value: R, block: F.(R) -> Unit): R
abstract fun variable(value: T): Variable<T>
public abstract fun variable(value: T): Variable<T>
inline fun variable(block: F.() -> T): Variable<T> = variable(context.block())
public inline fun variable(block: F.() -> T): Variable<T> = variable(context.block())
// Overloads for Double constants
@ -153,7 +153,6 @@ internal class AutoDiffContext<T : Any, F : Field<T>>(override val context: F) :
// Basic math (+, -, *, /)
override fun add(a: Variable<T>, b: Variable<T>): Variable<T> = derive(variable { a.value + b.value }) { z ->
a.d += z.d
b.d += z.d
@ -177,35 +176,36 @@ internal class AutoDiffContext<T : Any, F : Field<T>>(override val context: F) :
// Extensions for differentiation of various basic mathematical functions
// x ^ 2
fun <T : Any, F : Field<T>> AutoDiffField<T, F>.sqr(x: Variable<T>): Variable<T> =
public fun <T : Any, F : Field<T>> AutoDiffField<T, F>.sqr(x: Variable<T>): Variable<T> =
derive(variable { x.value * x.value }) { z -> x.d += z.d * 2 * x.value }
// x ^ 1/2
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.sqrt(x: Variable<T>): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.sqrt(x: Variable<T>): Variable<T> =
derive(variable { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value }
// x ^ y (const)
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.pow(x: Variable<T>, y: Double): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.pow(x: Variable<T>, y: Double): Variable<T> =
derive(variable { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) }
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.pow(x: Variable<T>, y: Int): Variable<T> = pow(x, y.toDouble())
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.pow(x: Variable<T>, y: Int): Variable<T> =
pow(x, y.toDouble())
// exp(x)
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.exp(x: Variable<T>): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.exp(x: Variable<T>): Variable<T> =
derive(variable { exp(x.value) }) { z -> x.d += z.d * z.value }
// ln(x)
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.ln(x: Variable<T>): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.ln(x: Variable<T>): Variable<T> =
derive(variable { ln(x.value) }) { z -> x.d += z.d / x.value }
// x ^ y (any)
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.pow(x: Variable<T>, y: Variable<T>): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.pow(x: Variable<T>, y: Variable<T>): Variable<T> =
exp(y * ln(x))
// sin(x)
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.sin(x: Variable<T>): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.sin(x: Variable<T>): Variable<T> =
derive(variable { sin(x.value) }) { z -> x.d += z.d * cos(x.value) }
// cos(x)
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.cos(x: Variable<T>): Variable<T> =
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.cos(x: Variable<T>): Variable<T> =
derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) }

@ -10,17 +10,21 @@ import kotlin.math.abs
*
* If step is negative, the same goes from upper boundary downwards
*/
fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Sequence<Double> = when {
public fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Sequence<Double> = when {
step == 0.0 -> error("Zero step in double progression")
step > 0 -> sequence {
var current = start
while (current <= endInclusive) {
yield(current)
current += step
}
}
else -> sequence {
var current = endInclusive
while (current >= start) {
yield(current)
current += step
@ -31,7 +35,7 @@ fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Sequence<
/**
* Convert double range to sequence with the fixed number of points
*/
fun ClosedFloatingPointRange<Double>.toSequenceWithPoints(numPoints: Int): Sequence<Double> {
public fun ClosedFloatingPointRange<Double>.toSequenceWithPoints(numPoints: Int): Sequence<Double> {
require(numPoints > 1) { "The number of points should be more than 2" }
return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1))
}
@ -40,7 +44,7 @@ fun ClosedFloatingPointRange<Double>.toSequenceWithPoints(numPoints: Int): Seque
* Convert double range to array of evenly spaced doubles, where the size of array equals [numPoints]
*/
@Deprecated("Replace by 'toSequenceWithPoints'")
fun ClosedFloatingPointRange<Double>.toGrid(numPoints: Int): DoubleArray {
public fun ClosedFloatingPointRange<Double>.toGrid(numPoints: Int): DoubleArray {
require(numPoints >= 2) { "Can't create generic grid with less than two points" }
return DoubleArray(numPoints) { i -> start + (endInclusive - start) / (numPoints - 1) * i }
}

@ -2,7 +2,6 @@ package scientifik.kmath.misc
import scientifik.kmath.operations.Space
import scientifik.kmath.operations.invoke
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.jvm.JvmName
@ -13,10 +12,8 @@ import kotlin.jvm.JvmName
* @param R the type of resulting iterable.
* @param initial lazy evaluated.
*/
inline fun <T, R> Iterator<T>.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterator<R> {
contract { callsInPlace(operation) }
return object : Iterator<R> {
public inline fun <T, R> Iterator<T>.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterator<R> =
object : Iterator<R> {
var state: R = initial
override fun hasNext(): Boolean = this@cumulative.hasNext()
@ -26,16 +23,14 @@ inline fun <T, R> Iterator<T>.cumulative(initial: R, crossinline operation: (R,
return state
}
}
}
inline fun <T, R> Iterable<T>.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterable<R> =
public inline fun <T, R> Iterable<T>.cumulative(initial: R, crossinline operation: (R, T) -> R): Iterable<R> =
Iterable { this@cumulative.iterator().cumulative(initial, operation) }
inline fun <T, R> Sequence<T>.cumulative(initial: R, crossinline operation: (R, T) -> R): Sequence<R> = Sequence {
this@cumulative.iterator().cumulative(initial, operation)
}
public inline fun <T, R> Sequence<T>.cumulative(initial: R, crossinline operation: (R, T) -> R): Sequence<R> =
Sequence { this@cumulative.iterator().cumulative(initial, operation) }
fun <T, R> List<T>.cumulative(initial: R, operation: (R, T) -> R): List<R> =
public fun <T, R> List<T>.cumulative(initial: R, operation: (R, T) -> R): List<R> =
iterator().cumulative(initial, operation).asSequence().toList()
//Cumulative sum
@ -43,38 +38,38 @@ fun <T, R> List<T>.cumulative(initial: R, operation: (R, T) -> R): List<R> =
/**
* Cumulative sum with custom space
*/
fun <T> Iterable<T>.cumulativeSum(space: Space<T>): Iterable<T> =
public fun <T> Iterable<T>.cumulativeSum(space: Space<T>): Iterable<T> =
space { cumulative(zero) { element: T, sum: T -> sum + element } }
@JvmName("cumulativeSumOfDouble")
fun Iterable<Double>.cumulativeSum(): Iterable<Double> = cumulative(0.0) { element, sum -> sum + element }
public fun Iterable<Double>.cumulativeSum(): Iterable<Double> = cumulative(0.0) { element, sum -> sum + element }
@JvmName("cumulativeSumOfInt")
fun Iterable<Int>.cumulativeSum(): Iterable<Int> = cumulative(0) { element, sum -> sum + element }
public fun Iterable<Int>.cumulativeSum(): Iterable<Int> = cumulative(0) { element, sum -> sum + element }
@JvmName("cumulativeSumOfLong")
fun Iterable<Long>.cumulativeSum(): Iterable<Long> = cumulative(0L) { element, sum -> sum + element }
public fun Iterable<Long>.cumulativeSum(): Iterable<Long> = cumulative(0L) { element, sum -> sum + element }
fun <T> Sequence<T>.cumulativeSum(space: Space<T>): Sequence<T> =
public fun <T> Sequence<T>.cumulativeSum(space: Space<T>): Sequence<T> =
space { cumulative(zero) { element: T, sum: T -> sum + element } }
@JvmName("cumulativeSumOfDouble")
fun Sequence<Double>.cumulativeSum(): Sequence<Double> = cumulative(0.0) { element, sum -> sum + element }
public fun Sequence<Double>.cumulativeSum(): Sequence<Double> = cumulative(0.0) { element, sum -> sum + element }
@JvmName("cumulativeSumOfInt")
fun Sequence<Int>.cumulativeSum(): Sequence<Int> = cumulative(0) { element, sum -> sum + element }
public fun Sequence<Int>.cumulativeSum(): Sequence<Int> = cumulative(0) { element, sum -> sum + element }
@JvmName("cumulativeSumOfLong")
fun Sequence<Long>.cumulativeSum(): Sequence<Long> = cumulative(0L) { element, sum -> sum + element }
public fun Sequence<Long>.cumulativeSum(): Sequence<Long> = cumulative(0L) { element, sum -> sum + element }
fun <T> List<T>.cumulativeSum(space: Space<T>): List<T> =
public fun <T> List<T>.cumulativeSum(space: Space<T>): List<T> =
space { cumulative(zero) { element: T, sum: T -> sum + element } }
@JvmName("cumulativeSumOfDouble")
fun List<Double>.cumulativeSum(): List<Double> = cumulative(0.0) { element, sum -> sum + element }
public fun List<Double>.cumulativeSum(): List<Double> = cumulative(0.0) { element, sum -> sum + element }
@JvmName("cumulativeSumOfInt")
fun List<Int>.cumulativeSum(): List<Int> = cumulative(0) { element, sum -> sum + element }
public fun List<Int>.cumulativeSum(): List<Int> = cumulative(0) { element, sum -> sum + element }
@JvmName("cumulativeSumOfLong")
fun List<Long>.cumulativeSum(): List<Long> = cumulative(0L) { element, sum -> sum + element }
public fun List<Long>.cumulativeSum(): List<Long> = cumulative(0L) { element, sum -> sum + element }

@ -1,31 +1,33 @@
package scientifik.kmath.operations
import kotlin.contracts.contract
/**
* Stub for DSL the [Algebra] is.
*/
@DslMarker
annotation class KMathContext
public annotation class KMathContext
/**
* Represents an algebraic structure.
*
* @param T the type of element of this structure.
*/
interface Algebra<T> {
public interface Algebra<T> {
/**
* Wrap raw string or variable
*/
fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this")
public fun symbol(value: String): T = error("Wrapping of '$value' is not supported in $this")
/**
* Dynamic call of unary operation with name [operation] on [arg]
*/
fun unaryOperation(operation: String, arg: T): T
public fun unaryOperation(operation: String, arg: T): T
/**
* Dynamic call of binary operation [operation] on [left] and [right]
*/
fun binaryOperation(operation: String, left: T, right: T): T
public fun binaryOperation(operation: String, left: T, right: T): T
}
/**
@ -33,29 +35,30 @@ interface Algebra<T> {
*
* @param T the type of element of this structure.
*/
interface NumericAlgebra<T> : Algebra<T> {
public interface NumericAlgebra<T> : Algebra<T> {
/**
* Wraps a number.
*/
fun number(value: Number): T
public fun number(value: Number): T
/**
* Dynamic call of binary operation [operation] on [left] and [right] where left element is [Number].
*/
fun leftSideNumberOperation(operation: String, left: Number, right: T): T =
public fun leftSideNumberOperation(operation: String, left: Number, right: T): T =
binaryOperation(operation, number(left), right)
/**
* Dynamic call of binary operation [operation] on [left] and [right] where right element is [Number].
*/
fun rightSideNumberOperation(operation: String, left: T, right: Number): T =
public fun rightSideNumberOperation(operation: String, left: T, right: Number): T =
leftSideNumberOperation(operation, right, left)
}
/**
* Call a block with an [Algebra] as receiver.
*/
inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(block)
// TODO add contract when KT-32313 is fixed
public inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = block()
/**
* Represents "semispace", i.e. algebraic structure with associative binary operation called "addition" as well as
@ -63,7 +66,7 @@ inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(bloc
*
* @param T the type of element of this semispace.
*/
interface SpaceOperations<T> : Algebra<T> {
public interface SpaceOperations<T> : Algebra<T> {
/**
* Addition of two elements.
*
@ -71,7 +74,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param b the augend.
* @return the sum.
*/
fun add(a: T, b: T): T
public fun add(a: T, b: T): T
/**
* Multiplication of element by scalar.
@ -80,7 +83,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param k the multiplicand.
* @return the produce.
*/
fun multiply(a: T, k: Number): T
public fun multiply(a: T, k: Number): T
// Operations to be performed in this context. Could be moved to extensions in case of KEEP-176
@ -90,7 +93,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @receiver this value.
* @return the additive inverse of this value.
*/
operator fun T.unaryMinus(): T = multiply(this, -1.0)
public operator fun T.unaryMinus(): T = multiply(this, -1.0)
/**
* Returns this value.
@ -98,7 +101,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @receiver this value.
* @return this value.
*/
operator fun T.unaryPlus(): T = this
public operator fun T.unaryPlus(): T = this
/**
* Addition of two elements.
@ -107,7 +110,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param b the augend.
* @return the sum.
*/
operator fun T.plus(b: T): T = add(this, b)
public operator fun T.plus(b: T): T = add(this, b)
/**
* Subtraction of two elements.
@ -116,7 +119,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param b the subtrahend.
* @return the difference.
*/
operator fun T.minus(b: T): T = add(this, -b)
public operator fun T.minus(b: T): T = add(this, -b)
/**
* Multiplication of this element by a scalar.
@ -125,7 +128,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param k the multiplicand.
* @return the product.
*/
operator fun T.times(k: Number): T = multiply(this, k.toDouble())
public operator fun T.times(k: Number): T = multiply(this, k.toDouble())
/**
* Division of this element by scalar.
@ -134,7 +137,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param k the divisor.
* @return the quotient.
*/
operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble())
public operator fun T.div(k: Number): T = multiply(this, 1.0 / k.toDouble())
/**
* Multiplication of this number by element.
@ -143,7 +146,7 @@ interface SpaceOperations<T> : Algebra<T> {
* @param b the multiplicand.
* @return the product.
*/
operator fun Number.times(b: T): T = b * this
public operator fun Number.times(b: T): T = b * this
override fun unaryOperation(operation: String, arg: T): T = when (operation) {
PLUS_OPERATION -> arg
@ -157,18 +160,16 @@ interface SpaceOperations<T> : Algebra<T> {
else -> error("Binary operation $operation not defined in $this")
}
companion object {
public companion object {
/**
* The identifier of addition.
*/
const val PLUS_OPERATION: String = "+"
public const val PLUS_OPERATION: String = "+"
/**
* The identifier of subtraction (and negation).
*/
const val MINUS_OPERATION: String = "-"
const val NOT_OPERATION: String = "!"
public const val MINUS_OPERATION: String = "-"
}
}
@ -178,11 +179,11 @@ interface SpaceOperations<T> : Algebra<T> {
*
* @param T the type of element of this group.
*/
interface Space<T> : SpaceOperations<T> {
public interface Space<T> : SpaceOperations<T> {
/**
* The neutral element of addition.
*/
val zero: T
public val zero: T
}
/**
@ -191,14 +192,14 @@ interface Space<T> : SpaceOperations<T> {
*
* @param T the type of element of this semiring.
*/
interface RingOperations<T> : SpaceOperations<T> {
public interface RingOperations<T> : SpaceOperations<T> {
/**
* Multiplies two elements.
*
* @param a the multiplier.
* @param b the multiplicand.
*/
fun multiply(a: T, b: T): T
public fun multiply(a: T, b: T): T
/**
* Multiplies this element by scalar.
@ -206,18 +207,18 @@ interface RingOperations<T> : SpaceOperations<T> {
* @receiver the multiplier.
* @param b the multiplicand.
*/
operator fun T.times(b: T): T = multiply(this, b)
public operator fun T.times(b: T): T = multiply(this, b)
override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) {
TIMES_OPERATION -> multiply(left, right)
else -> super.binaryOperation(operation, left, right)
}
companion object {
public companion object {
/**
* The identifier of multiplication.
*/
const val TIMES_OPERATION: String = "*"
public const val TIMES_OPERATION: String = "*"
}
}
@ -227,11 +228,11 @@ interface RingOperations<T> : SpaceOperations<T> {
*
* @param T the type of element of this ring.
*/
interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
public interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
/**
* neutral operation for multiplication
*/
val one: T
public val one: T
override fun number(value: Number): T = one * value.toDouble()
@ -255,7 +256,7 @@ interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
* @receiver the addend.
* @param b the augend.
*/
operator fun T.plus(b: Number): T = this + number(b)
public operator fun T.plus(b: Number): T = this + number(b)
/**
* Addition of scalar and element.
@ -263,7 +264,7 @@ interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
* @receiver the addend.
* @param b the augend.
*/
operator fun Number.plus(b: T): T = b + this
public operator fun Number.plus(b: T): T = b + this
/**
* Subtraction of element from number.
@ -272,7 +273,7 @@ interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
* @param b the subtrahend.
* @receiver the difference.
*/
operator fun T.minus(b: Number): T = this - number(b)
public operator fun T.minus(b: Number): T = this - number(b)
/**
* Subtraction of number from element.
@ -281,7 +282,7 @@ interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
* @param b the subtrahend.
* @receiver the difference.
*/
operator fun Number.minus(b: T): T = -b + this
public operator fun Number.minus(b: T): T = -b + this
}
/**
@ -290,7 +291,7 @@ interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
*
* @param T the type of element of this semifield.
*/
interface FieldOperations<T> : RingOperations<T> {
public interface FieldOperations<T> : RingOperations<T> {
/**
* Division of two elements.
*
@ -298,7 +299,7 @@ interface FieldOperations<T> : RingOperations<T> {
* @param b the divisor.
* @return the quotient.
*/
fun divide(a: T, b: T): T
public fun divide(a: T, b: T): T
/**
* Division of two elements.
@ -307,18 +308,18 @@ interface FieldOperations<T> : RingOperations<T> {
* @param b the divisor.
* @return the quotient.
*/
operator fun T.div(b: T): T = divide(this, b)
public operator fun T.div(b: T): T = divide(this, b)
override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) {
DIV_OPERATION -> divide(left, right)
else -> super.binaryOperation(operation, left, right)
}
companion object {
public companion object {
/**
* The identifier of division.
*/
const val DIV_OPERATION: String = "/"
public const val DIV_OPERATION: String = "/"
}
}
@ -328,7 +329,7 @@ interface FieldOperations<T> : RingOperations<T> {
*
* @param T the type of element of this semifield.
*/
interface Field<T> : Ring<T>, FieldOperations<T> {
public interface Field<T> : Ring<T>, FieldOperations<T> {
/**
* Division of element by scalar.
*
@ -336,5 +337,5 @@ interface Field<T> : Ring<T>, FieldOperations<T> {
* @param b the divisor.
* @return the quotient.
*/
operator fun Number.div(b: T): T = this * divide(one, b)
public operator fun Number.div(b: T): T = this * divide(one, b)
}

@ -5,11 +5,11 @@ package scientifik.kmath.operations
*
* @param C the type of mathematical context for this element.
*/
interface MathElement<C> {
public interface MathElement<C> {
/**
* The context this element belongs to.
*/
val context: C
public val context: C
}
/**
@ -18,16 +18,16 @@ interface MathElement<C> {
* @param T the type wrapped by this wrapper.
* @param I the type of this wrapper.
*/
interface MathWrapper<T, I> {
public interface MathWrapper<T, I> {
/**
* Unwraps [I] to [T].
*/
fun unwrap(): T
public fun unwrap(): T
/**
* Wraps [T] to [I].
*/
fun T.wrap(): I
public fun T.wrap(): I
}
/**
@ -37,14 +37,14 @@ interface MathWrapper<T, I> {
* @param I self type of the element. Needed for static type checking.
* @param S the type of space.
*/
interface SpaceElement<T, I : SpaceElement<T, I, S>, S : Space<T>> : MathElement<S>, MathWrapper<T, I> {
public interface SpaceElement<T, I : SpaceElement<T, I, S>, S : Space<T>> : MathElement<S>, MathWrapper<T, I> {
/**
* Adds element to this one.
*
* @param b the augend.
* @return the sum.
*/
operator fun plus(b: T): I = context.add(unwrap(), b).wrap()
public operator fun plus(b: T): I = context.add(unwrap(), b).wrap()
/**
* Subtracts element from this one.
@ -52,7 +52,7 @@ interface SpaceElement<T, I : SpaceElement<T, I, S>, S : Space<T>> : MathElement
* @param b the subtrahend.
* @return the difference.
*/
operator fun minus(b: T): I = context.add(unwrap(), context.multiply(b, -1.0)).wrap()
public operator fun minus(b: T): I = context.add(unwrap(), context.multiply(b, -1.0)).wrap()
/**
* Multiplies this element by number.
@ -60,7 +60,7 @@ interface SpaceElement<T, I : SpaceElement<T, I, S>, S : Space<T>> : MathElement
* @param k the multiplicand.
* @return the product.
*/
operator fun times(k: Number): I = context.multiply(unwrap(), k.toDouble()).wrap()
public operator fun times(k: Number): I = context.multiply(unwrap(), k.toDouble()).wrap()
/**
* Divides this element by number.
@ -68,7 +68,7 @@ interface SpaceElement<T, I : SpaceElement<T, I, S>, S : Space<T>> : MathElement
* @param k the divisor.
* @return the quotient.
*/
operator fun div(k: Number): I = context.multiply(unwrap(), 1.0 / k.toDouble()).wrap()
public operator fun div(k: Number): I = context.multiply(unwrap(), 1.0 / k.toDouble()).wrap()
}
/**
@ -78,14 +78,14 @@ interface SpaceElement<T, I : SpaceElement<T, I, S>, S : Space<T>> : MathElement
* @param I self type of the element. Needed for static type checking.
* @param R the type of space.
*/
interface RingElement<T, I : RingElement<T, I, R>, R : Ring<T>> : SpaceElement<T, I, R> {
public interface RingElement<T, I : RingElement<T, I, R>, R : Ring<T>> : SpaceElement<T, I, R> {
/**
* Multiplies this element by another one.
*
* @param b the multiplicand.
* @return the product.
*/
operator fun times(b: T): I = context.multiply(unwrap(), b).wrap()
public operator fun times(b: T): I = context.multiply(unwrap(), b).wrap()
}
/**
@ -95,7 +95,7 @@ interface RingElement<T, I : RingElement<T, I, R>, R : Ring<T>> : SpaceElement<T
* @param I self type of the element. Needed for static type checking.
* @param F the type of field.
*/
interface FieldElement<T, I : FieldElement<T, I, F>, F : Field<T>> : RingElement<T, I, F> {
public interface FieldElement<T, I : FieldElement<T, I, F>, F : Field<T>> : RingElement<T, I, F> {
override val context: F
/**
@ -104,5 +104,5 @@ interface FieldElement<T, I : FieldElement<T, I, F>, F : Field<T>> : RingElement
* @param b the divisor.
* @return the quotient.
*/
operator fun div(b: T): I = context.divide(unwrap(), b).wrap()
public operator fun div(b: T): I = context.divide(unwrap(), b).wrap()
}

@ -7,7 +7,7 @@ package scientifik.kmath.operations
* @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) }
public fun <T> Space<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> add(left, right) }
/**
* Returns the sum of all elements in the sequence in this [Space].
@ -16,7 +16,7 @@ fun <T> Space<T>.sum(data: Iterable<T>): T = data.fold(zero) { left, right -> ad
* @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) }
public 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].
@ -25,7 +25,7 @@ fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> ad
* @param data the iterable to find average.
* @return the average value.
*/
fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
public 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].
@ -34,7 +34,7 @@ fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
* @param data the sequence to find average.
* @return the average value.
*/
fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
public 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.
@ -43,7 +43,7 @@ fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
* @param space the algebra that provides addition.
* @return the sum.
*/
fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
public fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
/**
* Returns the sum of all elements in the sequence in provided space.
@ -52,7 +52,7 @@ fun <T> Iterable<T>.sumWith(space: Space<T>): T = space.sum(this)
* @param space the algebra that provides addition.
* @return the sum.
*/
fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
public fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
/**
* Returns an average value of elements in the iterable in this [Space].
@ -61,7 +61,7 @@ fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
* @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)
public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
/**
* Returns an average value of elements in the sequence in this [Space].
@ -70,7 +70,7 @@ fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
* @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)
public fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
//TODO optimized power operation
@ -82,7 +82,7 @@ fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
* @param power the exponent.
* @return the base raised to the power.
*/
fun <T> Ring<T>.power(arg: T, power: Int): T {
public fun <T> Ring<T>.power(arg: T, power: Int): T {
require(power >= 0) { "The power can't be negative." }
require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." }
if (power == 0) return one
@ -99,7 +99,7 @@ fun <T> Ring<T>.power(arg: T, power: Int): T {
* @param power the exponent.
* @return the base raised to the power.
*/
fun <T> Field<T>.power(arg: T, power: Int): T {
public fun <T> Field<T>.power(arg: T, power: Int): T {
require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." }
if (power == 0) return one
if (power < 0) return one / (this as Ring<T>).power(arg, -power)

@ -3,22 +3,21 @@ package scientifik.kmath.operations
import scientifik.kmath.operations.BigInt.Companion.BASE
import scientifik.kmath.operations.BigInt.Companion.BASE_SIZE
import scientifik.kmath.structures.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.math.log2
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sign
typealias Magnitude = UIntArray
typealias TBase = ULong
public typealias Magnitude = UIntArray
public typealias TBase = ULong
/**
* Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger).
*
* @author Robert Drynkin (https://github.com/robdrynkin) and Peter Klimai (https://github.com/pklimai)
*/
object BigIntField : Field<BigInt> {
public object BigIntField : Field<BigInt> {
override val zero: BigInt = BigInt.ZERO
override val one: BigInt = BigInt.ONE
@ -29,113 +28,92 @@ object BigIntField : Field<BigInt> {
override fun multiply(a: BigInt, b: BigInt): BigInt = a.times(b)
operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer")
public operator fun String.unaryPlus(): BigInt = this.parseBigInteger() ?: error("Can't parse $this as big integer")
operator fun String.unaryMinus(): BigInt =
public operator fun String.unaryMinus(): BigInt =
-(this.parseBigInteger() ?: error("Can't parse $this as big integer"))
override fun divide(a: BigInt, b: BigInt): BigInt = a.div(b)
}
class BigInt internal constructor(
public class BigInt internal constructor(
private val sign: Byte,
private val magnitude: Magnitude
) : Comparable<BigInt> {
public override fun compareTo(other: BigInt): Int = when {
(sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0
sign < other.sign -> -1
sign > other.sign -> 1
else -> sign * compareMagnitudes(magnitude, other.magnitude)
}
override fun compareTo(other: BigInt): Int {
return when {
(this.sign == 0.toByte()) and (other.sign == 0.toByte()) -> 0
this.sign < other.sign -> -1
this.sign > other.sign -> 1
else -> this.sign * compareMagnitudes(this.magnitude, other.magnitude)
public override fun equals(other: Any?): Boolean =
if (other is BigInt) compareTo(other) == 0 else error("Can't compare KBigInteger to a different type")
public override fun hashCode(): Int = magnitude.hashCode() + sign
public fun abs(): BigInt = if (sign == 0.toByte()) this else BigInt(1, magnitude)
public operator fun unaryMinus(): BigInt =
if (this.sign == 0.toByte()) this else BigInt((-this.sign).toByte(), this.magnitude)
public operator fun plus(b: BigInt): BigInt = when {
b.sign == 0.toByte() -> this
sign == 0.toByte() -> b
this == -b -> ZERO
sign == b.sign -> BigInt(sign, addMagnitudes(magnitude, b.magnitude))
else -> {
val comp = compareMagnitudes(magnitude, b.magnitude)
if (comp == 1)
BigInt(sign, subtractMagnitudes(magnitude, b.magnitude))
else
BigInt((-sign).toByte(), subtractMagnitudes(b.magnitude, magnitude))
}
}
override fun equals(other: Any?): Boolean {
if (other is BigInt) {
return this.compareTo(other) == 0
} else error("Can't compare KBigInteger to a different type")
}
public operator fun minus(b: BigInt): BigInt = this + (-b)
override fun hashCode(): Int {
return magnitude.hashCode() + this.sign
}
fun abs(): BigInt = if (sign == 0.toByte()) this else BigInt(1, magnitude)
operator fun unaryMinus(): BigInt {
return if (this.sign == 0.toByte()) this else BigInt((-this.sign).toByte(), this.magnitude)
}
operator fun plus(b: BigInt): BigInt {
return when {
b.sign == 0.toByte() -> this
this.sign == 0.toByte() -> b
this == -b -> ZERO
this.sign == b.sign -> BigInt(this.sign, addMagnitudes(this.magnitude, b.magnitude))
else -> {
val comp: Int = compareMagnitudes(this.magnitude, b.magnitude)
if (comp == 1) {
BigInt(this.sign, subtractMagnitudes(this.magnitude, b.magnitude))
} else {
BigInt((-this.sign).toByte(), subtractMagnitudes(b.magnitude, this.magnitude))
}
}
}
}
operator fun minus(b: BigInt): BigInt {
return this + (-b)
}
operator fun times(b: BigInt): BigInt {
return when {
this.sign == 0.toByte() -> ZERO
b.sign == 0.toByte() -> ZERO
public operator fun times(b: BigInt): BigInt = when {
this.sign == 0.toByte() -> ZERO
b.sign == 0.toByte() -> ZERO
// TODO: Karatsuba
else -> BigInt((this.sign * b.sign).toByte(), multiplyMagnitudes(this.magnitude, b.magnitude))
}
else -> BigInt((this.sign * b.sign).toByte(), multiplyMagnitudes(this.magnitude, b.magnitude))
}
operator fun times(other: UInt): BigInt {
return when {
this.sign == 0.toByte() -> ZERO
other == 0U -> ZERO
else -> BigInt(this.sign, multiplyMagnitudeByUInt(this.magnitude, other))
}
public operator fun times(other: UInt): BigInt = when {
sign == 0.toByte() -> ZERO
other == 0U -> ZERO
else -> BigInt(sign, multiplyMagnitudeByUInt(magnitude, other))
}
operator fun times(other: Int): BigInt {
return if (other > 0)
this * kotlin.math.abs(other).toUInt()
else
-this * kotlin.math.abs(other).toUInt()
}
public operator fun times(other: Int): BigInt = if (other > 0)
this * kotlin.math.abs(other).toUInt()
else
-this * kotlin.math.abs(other).toUInt()
operator fun div(other: UInt): BigInt {
return BigInt(this.sign, divideMagnitudeByUInt(this.magnitude, other))
}
public operator fun div(other: UInt): BigInt = BigInt(this.sign, divideMagnitudeByUInt(this.magnitude, other))
operator fun div(other: Int): BigInt {
return BigInt(
(this.sign * other.sign).toByte(),
divideMagnitudeByUInt(this.magnitude, kotlin.math.abs(other).toUInt())
)
}
public operator fun div(other: Int): BigInt = BigInt(
(this.sign * other.sign).toByte(),
divideMagnitudeByUInt(this.magnitude, kotlin.math.abs(other).toUInt())
)
private fun division(other: BigInt): Pair<BigInt, BigInt> {
// Long division algorithm:
// https://en.wikipedia.org/wiki/Division_algorithm#Integer_division_(unsigned)_with_remainder
// TODO: Implement more effective algorithm
var q: BigInt = ZERO
var r: BigInt = ZERO
var q = ZERO
var r = ZERO
val bitSize =
(BASE_SIZE * (this.magnitude.size - 1) + log2(this.magnitude.lastOrNull()?.toFloat() ?: 0f + 1)).toInt()
for (i in bitSize downTo 0) {
r = r shl 1
r = r or ((abs(this) shr i) and ONE)
if (r >= abs(other)) {
r -= abs(other)
q += (ONE shl i)
@ -145,99 +123,84 @@ class BigInt internal constructor(
return Pair(BigInt((this.sign * other.sign).toByte(), q.magnitude), r)
}
operator fun div(other: BigInt): BigInt {
return this.division(other).first
}
public operator fun div(other: BigInt): BigInt = division(other).first
infix fun shl(i: Int): BigInt {
public infix fun shl(i: Int): BigInt {
if (this == ZERO) return ZERO
if (i == 0) return this
val fullShifts = i / BASE_SIZE + 1
val relShift = i % BASE_SIZE
val shiftLeft = { x: UInt -> if (relShift >= 32) 0U else x shl relShift }
val shiftRight = { x: UInt -> if (BASE_SIZE - relShift >= 32) 0U else x shr (BASE_SIZE - relShift) }
val newMagnitude = Magnitude(magnitude.size + fullShifts)
val newMagnitude: Magnitude = Magnitude(this.magnitude.size + fullShifts)
for (j in this.magnitude.indices) {
for (j in magnitude.indices) {
newMagnitude[j + fullShifts - 1] = shiftLeft(this.magnitude[j])
if (j != 0) {
if (j != 0)
newMagnitude[j + fullShifts - 1] = newMagnitude[j + fullShifts - 1] or shiftRight(this.magnitude[j - 1])
}
}
newMagnitude[this.magnitude.size + fullShifts - 1] = shiftRight(this.magnitude.last())
newMagnitude[magnitude.size + fullShifts - 1] = shiftRight(magnitude.last())
return BigInt(this.sign, stripLeadingZeros(newMagnitude))
}
infix fun shr(i: Int): BigInt {
public infix fun shr(i: Int): BigInt {
if (this == ZERO) return ZERO
if (i == 0) return this
val fullShifts = i / BASE_SIZE
val relShift = i % BASE_SIZE
val shiftRight = { x: UInt -> if (relShift >= 32) 0U else x shr relShift }
val shiftLeft = { x: UInt -> if (BASE_SIZE - relShift >= 32) 0U else x shl (BASE_SIZE - relShift) }
if (this.magnitude.size - fullShifts <= 0) {
return ZERO
}
val newMagnitude: Magnitude = Magnitude(this.magnitude.size - fullShifts)
if (this.magnitude.size - fullShifts <= 0) return ZERO
val newMagnitude: Magnitude = Magnitude(magnitude.size - fullShifts)
for (j in fullShifts until this.magnitude.size) {
newMagnitude[j - fullShifts] = shiftRight(this.magnitude[j])
if (j != this.magnitude.size - 1) {
newMagnitude[j - fullShifts] = newMagnitude[j - fullShifts] or shiftLeft(this.magnitude[j + 1])
}
for (j in fullShifts until magnitude.size) {
newMagnitude[j - fullShifts] = shiftRight(magnitude[j])
if (j != magnitude.size - 1)
newMagnitude[j - fullShifts] = newMagnitude[j - fullShifts] or shiftLeft(magnitude[j + 1])
}
return BigInt(this.sign, stripLeadingZeros(newMagnitude))
}
infix fun or(other: BigInt): BigInt {
public infix fun or(other: BigInt): BigInt {
if (this == ZERO) return other
if (other == ZERO) return this
val resSize = max(this.magnitude.size, other.magnitude.size)
val resSize = max(magnitude.size, other.magnitude.size)
val newMagnitude: Magnitude = Magnitude(resSize)
for (i in 0 until resSize) {
if (i < this.magnitude.size) {
newMagnitude[i] = newMagnitude[i] or this.magnitude[i]
}
if (i < other.magnitude.size) {
newMagnitude[i] = newMagnitude[i] or other.magnitude[i]
}
if (i < magnitude.size) newMagnitude[i] = newMagnitude[i] or magnitude[i]
if (i < other.magnitude.size) newMagnitude[i] = newMagnitude[i] or other.magnitude[i]
}
return BigInt(1, stripLeadingZeros(newMagnitude))
}
infix fun and(other: BigInt): BigInt {
public infix fun and(other: BigInt): BigInt {
if ((this == ZERO) or (other == ZERO)) return ZERO
val resSize = min(this.magnitude.size, other.magnitude.size)
val newMagnitude: Magnitude = Magnitude(resSize)
for (i in 0 until resSize) {
newMagnitude[i] = this.magnitude[i] and other.magnitude[i]
}
for (i in 0 until resSize) newMagnitude[i] = this.magnitude[i] and other.magnitude[i]
return BigInt(1, stripLeadingZeros(newMagnitude))
}
operator fun rem(other: Int): Int {
public operator fun rem(other: Int): Int {
val res = this - (this / other) * other
return if (res == ZERO) 0 else res.sign * res.magnitude[0].toInt()
}
operator fun rem(other: BigInt): BigInt {
return this - (this / other) * other
}
public operator fun rem(other: BigInt): BigInt = this - (this / other) * other
fun modPow(exponent: BigInt, m: BigInt): BigInt {
return when {
exponent == ZERO -> ONE
exponent % 2 == 1 -> (this * modPow(exponent - ONE, m)) % m
else -> {
val sqRoot = modPow(exponent / 2, m)
(sqRoot * sqRoot) % m
}
public fun modPow(exponent: BigInt, m: BigInt): BigInt = when {
exponent == ZERO -> ONE
exponent % 2 == 1 -> (this * modPow(exponent - ONE, m)) % m
else -> {
val sqRoot = modPow(exponent / 2, m)
(sqRoot * sqRoot) % m
}
}
@ -261,11 +224,11 @@ class BigInt internal constructor(
return res
}
companion object {
const val BASE: ULong = 0xffffffffUL
const val BASE_SIZE: Int = 32
val ZERO: BigInt = BigInt(0, uintArrayOf())
val ONE: BigInt = BigInt(1, uintArrayOf(1u))
public companion object {
public const val BASE: ULong = 0xffffffffUL
public const val BASE_SIZE: Int = 32
public val ZERO: BigInt = BigInt(0, uintArrayOf())
public val ONE: BigInt = BigInt(1, uintArrayOf(1u))
private val hexMapping: HashMap<UInt, String> = hashMapOf(
0U to "0", 1U to "1", 2U to "2", 3U to "3",
@ -292,9 +255,9 @@ class BigInt internal constructor(
}
private fun addMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude {
val resultLength: Int = max(mag1.size, mag2.size) + 1
val resultLength = max(mag1.size, mag2.size) + 1
val result = Magnitude(resultLength)
var carry: TBase = 0UL
var carry = 0uL
for (i in 0 until resultLength - 1) {
val res = when {
@ -302,20 +265,22 @@ class BigInt internal constructor(
i >= mag2.size -> mag1[i].toULong() + carry
else -> mag1[i].toULong() + mag2[i].toULong() + carry
}
result[i] = (res and BASE).toUInt()
carry = (res shr BASE_SIZE)
}
result[resultLength - 1] = carry.toUInt()
return stripLeadingZeros(result)
}
private fun subtractMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude {
val resultLength: Int = mag1.size
val resultLength = mag1.size
val result = Magnitude(resultLength)
var carry = 0L
for (i in 0 until resultLength) {
var res: Long =
var res =
if (i < mag2.size) mag1[i].toLong() - mag2[i].toLong() - carry
else mag1[i].toLong() - carry
@ -329,9 +294,9 @@ class BigInt internal constructor(
}
private fun multiplyMagnitudeByUInt(mag: Magnitude, x: UInt): Magnitude {
val resultLength: Int = mag.size + 1
val resultLength = mag.size + 1
val result = Magnitude(resultLength)
var carry: ULong = 0UL
var carry = 0uL
for (i in mag.indices) {
val cur: ULong = carry + mag[i].toULong() * x.toULong()
@ -344,16 +309,18 @@ class BigInt internal constructor(
}
private fun multiplyMagnitudes(mag1: Magnitude, mag2: Magnitude): Magnitude {
val resultLength: Int = mag1.size + mag2.size
val resultLength = mag1.size + mag2.size
val result = Magnitude(resultLength)
for (i in mag1.indices) {
var carry: ULong = 0UL
var carry = 0uL
for (j in mag2.indices) {
val cur: ULong = result[i + j].toULong() + mag1[i].toULong() * mag2[j].toULong() + carry
result[i + j] = (cur and BASE.toULong()).toUInt()
carry = cur shr BASE_SIZE
}
result[i + mag2.size] = (carry and BASE).toUInt()
}
@ -361,48 +328,46 @@ class BigInt internal constructor(
}
private fun divideMagnitudeByUInt(mag: Magnitude, x: UInt): Magnitude {
val resultLength: Int = mag.size
val resultLength = mag.size
val result = Magnitude(resultLength)
var carry: ULong = 0UL
var carry = 0uL
for (i in mag.size - 1 downTo 0) {
val cur: ULong = mag[i].toULong() + (carry shl BASE_SIZE)
result[i] = (cur / x).toUInt()
carry = cur % x
}
return stripLeadingZeros(result)
}
}
}
private fun stripLeadingZeros(mag: Magnitude): Magnitude {
if (mag.isEmpty() || mag.last() != 0U) {
return mag
}
var resSize: Int = mag.size - 1
if (mag.isEmpty() || mag.last() != 0U) return mag
var resSize = mag.size - 1
while (mag[resSize] == 0U) {
if (resSize == 0)
break
if (resSize == 0) break
resSize -= 1
}
return mag.sliceArray(IntRange(0, resSize))
}
fun abs(x: BigInt): BigInt = x.abs()
public fun abs(x: BigInt): BigInt = x.abs()
/**
* Convert this [Int] to [BigInt]
*/
fun Int.toBigInt(): BigInt = BigInt(sign.toByte(), uintArrayOf(kotlin.math.abs(this).toUInt()))
public fun Int.toBigInt(): BigInt = BigInt(sign.toByte(), uintArrayOf(kotlin.math.abs(this).toUInt()))
/**
* Convert this [Long] to [BigInt]
*/
fun Long.toBigInt(): BigInt = BigInt(
sign.toByte(), stripLeadingZeros(
public fun Long.toBigInt(): BigInt = BigInt(
sign.toByte(),
stripLeadingZeros(
uintArrayOf(
(kotlin.math.abs(this).toULong() and BASE).toUInt(),
((kotlin.math.abs(this).toULong() shr BASE_SIZE) and BASE).toUInt()
@ -413,12 +378,12 @@ fun Long.toBigInt(): BigInt = BigInt(
/**
* Convert UInt to [BigInt]
*/
fun UInt.toBigInt(): BigInt = BigInt(1, uintArrayOf(this))
public fun UInt.toBigInt(): BigInt = BigInt(1, uintArrayOf(this))
/**
* Convert ULong to [BigInt]
*/
fun ULong.toBigInt(): BigInt = BigInt(
public fun ULong.toBigInt(): BigInt = BigInt(
1,
stripLeadingZeros(
uintArrayOf(
@ -431,12 +396,12 @@ fun ULong.toBigInt(): BigInt = BigInt(
/**
* Create a [BigInt] with this array of magnitudes with protective copy
*/
fun UIntArray.toBigInt(sign: Byte): BigInt {
public fun UIntArray.toBigInt(sign: Byte): BigInt {
require(sign != 0.toByte() || !isNotEmpty())
return BigInt(sign, copyOf())
}
val hexChToInt: MutableMap<Char, Int> = hashMapOf(
private val hexChToInt: MutableMap<Char, Int> = hashMapOf(
'0' to 0, '1' to 1, '2' to 2, '3' to 3,
'4' to 4, '5' to 5, '6' to 6, '7' to 7,
'8' to 8, '9' to 9, 'A' to 10, 'B' to 11,
@ -446,9 +411,10 @@ val hexChToInt: MutableMap<Char, Int> = hashMapOf(
/**
* Returns null if a valid number can not be read from a string
*/
fun String.parseBigInteger(): BigInt? {
public fun String.parseBigInteger(): BigInt? {
val sign: Int
val sPositive: String
when {
this[0] == '+' -> {
sign = +1
@ -463,43 +429,42 @@ fun String.parseBigInteger(): BigInt? {
sign = +1
}
}
var res = BigInt.ZERO
var digitValue = BigInt.ONE
val sPositiveUpper = sPositive.toUpperCase()
if (sPositiveUpper.startsWith("0X")) { // hex representation
val sHex = sPositiveUpper.substring(2)
for (ch in sHex.reversed()) {
if (ch == '_') continue
res += digitValue * (hexChToInt[ch] ?: return null)
digitValue *= 16.toBigInt()
}
} else { // decimal representation
for (ch in sPositiveUpper.reversed()) {
if (ch == '_') continue
if (ch !in '0'..'9') {
return null
}
res += digitValue * (ch.toInt() - '0'.toInt())
digitValue *= 10.toBigInt()
} else for (ch in sPositiveUpper.reversed()) {
// decimal representation
if (ch == '_') continue
if (ch !in '0'..'9') {
return null
}
res += digitValue * (ch.toInt() - '0'.toInt())
digitValue *= 10.toBigInt()
}
return res * sign
}
inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> {
contract { callsInPlace(initializer) }
return boxing(size, initializer)
}
public inline fun Buffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): Buffer<BigInt> =
boxing(size, initializer)
inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer<BigInt> {
contract { callsInPlace(initializer) }
return boxing(size, initializer)
}
public inline fun MutableBuffer.Companion.bigInt(size: Int, initializer: (Int) -> BigInt): MutableBuffer<BigInt> =
boxing(size, initializer)
fun NDAlgebra.Companion.bigInt(vararg shape: Int): BoxingNDRing<BigInt, BigIntField> =
public fun NDAlgebra.Companion.bigInt(vararg shape: Int): BoxingNDRing<BigInt, BigIntField> =
BoxingNDRing(shape, BigIntField, Buffer.Companion::bigInt)
fun NDElement.Companion.bigInt(
public fun NDElement.Companion.bigInt(
vararg shape: Int,
initializer: BigIntField.(IntArray) -> BigInt
): BufferedNDRingElement<BigInt, BigIntField> = NDAlgebra.bigInt(*shape).produce(initializer)

@ -6,20 +6,18 @@ import scientifik.kmath.structures.MutableBuffer
import scientifik.memory.MemoryReader
import scientifik.memory.MemorySpec
import scientifik.memory.MemoryWriter
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.math.*
/**
* This complex's conjugate.
*/
val Complex.conjugate: Complex
public val Complex.conjugate: Complex
get() = Complex(re, -im)
/**
* This complex's reciprocal.
*/
val Complex.reciprocal: Complex
public val Complex.reciprocal: Complex
get() {
val scale = re * re + im * im
return Complex(re / scale, -im / scale)
@ -28,13 +26,13 @@ val Complex.reciprocal: Complex
/**
* Absolute value of complex number.
*/
val Complex.r: Double
public val Complex.r: Double
get() = sqrt(re * re + im * im)
/**
* An angle between vector represented by complex number and X axis.
*/
val Complex.theta: Double
public val Complex.theta: Double
get() = atan(im / re)
private val PI_DIV_2 = Complex(PI / 2, 0)
@ -42,14 +40,14 @@ private val PI_DIV_2 = Complex(PI / 2, 0)
/**
* A field of [Complex].
*/
object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
public object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
override val zero: Complex = 0.0.toComplex()
override val one: Complex = 1.0.toComplex()
/**
* The imaginary unit.
*/
val i: Complex = Complex(0.0, 1.0)
public val i: Complex = Complex(0.0, 1.0)
override fun add(a: Complex, b: Complex): Complex = Complex(a.re + b.re, a.im + b.im)
@ -117,7 +115,7 @@ object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
* @param c the augend.
* @return the sum.
*/
operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c)
public operator fun Double.plus(c: Complex): Complex = add(this.toComplex(), c)
/**
* Subtracts complex number from real one.
@ -126,7 +124,7 @@ object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
* @param c the subtrahend.
* @return the difference.
*/
operator fun Double.minus(c: Complex): Complex = add(this.toComplex(), -c)
public operator fun Double.minus(c: Complex): Complex = add(this.toComplex(), -c)
/**
* Adds real number to complex one.
@ -135,7 +133,7 @@ object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
* @param d the augend.
* @return the sum.
*/
operator fun Complex.plus(d: Double): Complex = d + this
public operator fun Complex.plus(d: Double): Complex = d + this
/**
* Subtracts real number from complex one.
@ -144,7 +142,7 @@ object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
* @param d the subtrahend.
* @return the difference.
*/
operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex())
public operator fun Complex.minus(d: Double): Complex = add(this, -d.toComplex())
/**
* Multiplies real number by complex one.
@ -153,7 +151,7 @@ object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
* @param c the multiplicand.
* @receiver the product.
*/
operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this)
public operator fun Double.times(c: Complex): Complex = Complex(c.re * this, c.im * this)
override fun norm(arg: Complex): Complex = sqrt(arg.conjugate * arg)
@ -166,8 +164,9 @@ object ComplexField : ExtendedField<Complex>, Norm<Complex, Complex> {
* @property re The real part.
* @property im The imaginary part.
*/
data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Complex, ComplexField>, Comparable<Complex> {
constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
public data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Complex, ComplexField>,
Comparable<Complex> {
public constructor(re: Number, im: Number) : this(re.toDouble(), im.toDouble())
override val context: ComplexField get() = ComplexField
@ -177,7 +176,7 @@ data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Compl
override fun compareTo(other: Complex): Int = r.compareTo(other.r)
companion object : MemorySpec<Complex> {
public companion object : MemorySpec<Complex> {
override val objectSize: Int = 16
override fun MemoryReader.read(offset: Int): Complex =
@ -196,14 +195,10 @@ data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Compl
* @receiver the real part.
* @return the new complex number.
*/
fun Number.toComplex(): Complex = Complex(this, 0.0)
public fun Number.toComplex(): Complex = Complex(this, 0.0)
inline fun Buffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer<Complex> {
contract { callsInPlace(init) }
return MemoryBuffer.create(Complex, size, init)
}
public inline fun Buffer.Companion.complex(size: Int, init: (Int) -> Complex): Buffer<Complex> =
MemoryBuffer.create(Complex, size, init)
inline fun MutableBuffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer<Complex> {
contract { callsInPlace(init) }
return MemoryBuffer.create(Complex, size, init)
}
public inline fun MutableBuffer.Companion.complex(size: Int, init: (Int) -> Complex): Buffer<Complex> =
MemoryBuffer.create(Complex, size, init)

@ -1,23 +1,21 @@
package scientifik.kmath.operations
import scientifik.kmath.operations.RealField.pow
import kotlin.math.abs
import kotlin.math.pow as kpow
/**
* Advanced Number-like semifield that implements basic operations.
*/
interface ExtendedFieldOperations<T> :
public interface ExtendedFieldOperations<T> :
FieldOperations<T>,
TrigonometricOperations<T>,
HyperbolicOperations<T>,
PowerOperations<T>,
ExponentialOperations<T> {
public override fun tan(arg: T): T = sin(arg) / cos(arg)
public override fun tanh(arg: T): T = sinh(arg) / cosh(arg)
override fun tan(arg: T): T = sin(arg) / cos(arg)
override fun tanh(arg: T): T = sinh(arg) / cosh(arg)
override fun unaryOperation(operation: String, arg: T): T = when (operation) {
public override fun unaryOperation(operation: String, arg: T): T = when (operation) {
TrigonometricOperations.COS_OPERATION -> cos(arg)
TrigonometricOperations.SIN_OPERATION -> sin(arg)
TrigonometricOperations.TAN_OPERATION -> tan(arg)
@ -37,19 +35,18 @@ interface ExtendedFieldOperations<T> :
}
}
/**
* Advanced Number-like field that implements basic operations.
*/
interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg)
override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
public interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
public override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
public override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
public override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
public override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg)
public override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
public override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) {
public override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) {
PowerOperations.POW_OPERATION -> power(left, right)
else -> super.rightSideNumberOperation(operation, left, right)
}
@ -62,209 +59,208 @@ interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
*
* TODO inline does not work due to compiler bug. Waiting for fix for KT-27586
*/
inline class Real(val value: Double) : FieldElement<Double, Real, RealField> {
override val context: RealField
public inline class Real(public val value: Double) : FieldElement<Double, Real, RealField> {
public override val context: RealField
get() = RealField
override fun unwrap(): Double = value
public override fun unwrap(): Double = value
public override fun Double.wrap(): Real = Real(value)
override fun Double.wrap(): Real = Real(value)
companion object
public companion object
}
/**
* A field for [Double] without boxing. Does not produce appropriate field element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object RealField : ExtendedField<Double>, Norm<Double, Double> {
override val zero: Double
public object RealField : ExtendedField<Double>, Norm<Double, Double> {
public override val zero: Double
get() = 0.0
override val one: Double
public override val one: Double
get() = 1.0
override fun binaryOperation(operation: String, left: Double, right: Double): Double = when (operation) {
public override fun binaryOperation(operation: String, left: Double, right: Double): Double = when (operation) {
PowerOperations.POW_OPERATION -> left pow right
else -> super.binaryOperation(operation, left, right)
}
override inline fun add(a: Double, b: Double): Double = a + b
override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble()
public override inline fun add(a: Double, b: Double): Double = a + b
public override inline fun multiply(a: Double, k: Number): Double = a * k.toDouble()
override inline fun multiply(a: Double, b: Double): Double = a * b
public override inline fun multiply(a: Double, b: Double): Double = a * b
override inline fun divide(a: Double, b: Double): Double = a / b
public override inline fun divide(a: Double, b: Double): Double = a / b
override inline fun sin(arg: Double): Double = kotlin.math.sin(arg)
override inline fun cos(arg: Double): Double = kotlin.math.cos(arg)
override inline fun tan(arg: Double): Double = kotlin.math.tan(arg)
override inline fun acos(arg: Double): Double = kotlin.math.acos(arg)
override inline fun asin(arg: Double): Double = kotlin.math.asin(arg)
override inline fun atan(arg: Double): Double = kotlin.math.atan(arg)
public override inline fun sin(arg: Double): Double = kotlin.math.sin(arg)
public override inline fun cos(arg: Double): Double = kotlin.math.cos(arg)
public override inline fun tan(arg: Double): Double = kotlin.math.tan(arg)
public override inline fun acos(arg: Double): Double = kotlin.math.acos(arg)
public override inline fun asin(arg: Double): Double = kotlin.math.asin(arg)
public override inline fun atan(arg: Double): Double = kotlin.math.atan(arg)
override inline fun sinh(arg: Double): Double = kotlin.math.sinh(arg)
override inline fun cosh(arg: Double): Double = kotlin.math.cosh(arg)
override inline fun tanh(arg: Double): Double = kotlin.math.tanh(arg)
override inline fun asinh(arg: Double): Double = kotlin.math.asinh(arg)
override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg)
override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg)
public override inline fun sinh(arg: Double): Double = kotlin.math.sinh(arg)
public override inline fun cosh(arg: Double): Double = kotlin.math.cosh(arg)
public override inline fun tanh(arg: Double): Double = kotlin.math.tanh(arg)
public override inline fun asinh(arg: Double): Double = kotlin.math.asinh(arg)
public override inline fun acosh(arg: Double): Double = kotlin.math.acosh(arg)
public override inline fun atanh(arg: Double): Double = kotlin.math.atanh(arg)
override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble())
override inline fun exp(arg: Double): Double = kotlin.math.exp(arg)
override inline fun ln(arg: Double): Double = kotlin.math.ln(arg)
public override inline fun power(arg: Double, pow: Number): Double = arg.kpow(pow.toDouble())
public override inline fun exp(arg: Double): Double = kotlin.math.exp(arg)
public override inline fun ln(arg: Double): Double = kotlin.math.ln(arg)
override inline fun norm(arg: Double): Double = abs(arg)
public override inline fun norm(arg: Double): Double = abs(arg)
override inline fun Double.unaryMinus(): Double = -this
override inline fun Double.plus(b: Double): Double = this + b
override inline fun Double.minus(b: Double): Double = this - b
override inline fun Double.times(b: Double): Double = this * b
override inline fun Double.div(b: Double): Double = this / b
public override inline fun Double.unaryMinus(): Double = -this
public override inline fun Double.plus(b: Double): Double = this + b
public override inline fun Double.minus(b: Double): Double = this - b
public override inline fun Double.times(b: Double): Double = this * b
public override inline fun Double.div(b: Double): Double = this / b
}
/**
* A field for [Float] without boxing. Does not produce appropriate field element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object FloatField : ExtendedField<Float>, Norm<Float, Float> {
override val zero: Float
public object FloatField : ExtendedField<Float>, Norm<Float, Float> {
public override val zero: Float
get() = 0.0f
override val one: Float
public override val one: Float
get() = 1.0f
override fun binaryOperation(operation: String, left: Float, right: Float): Float = when (operation) {
public override fun binaryOperation(operation: String, left: Float, right: Float): Float = when (operation) {
PowerOperations.POW_OPERATION -> left pow right
else -> super.binaryOperation(operation, left, right)
}
override inline fun add(a: Float, b: Float): Float = a + b
override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat()
public override inline fun add(a: Float, b: Float): Float = a + b
public override inline fun multiply(a: Float, k: Number): Float = a * k.toFloat()
override inline fun multiply(a: Float, b: Float): Float = a * b
public override inline fun multiply(a: Float, b: Float): Float = a * b
override inline fun divide(a: Float, b: Float): Float = a / b
public override inline fun divide(a: Float, b: Float): Float = a / b
override inline fun sin(arg: Float): Float = kotlin.math.sin(arg)
override inline fun cos(arg: Float): Float = kotlin.math.cos(arg)
override inline fun tan(arg: Float): Float = kotlin.math.tan(arg)
override inline fun acos(arg: Float): Float = kotlin.math.acos(arg)
override inline fun asin(arg: Float): Float = kotlin.math.asin(arg)
override inline fun atan(arg: Float): Float = kotlin.math.atan(arg)
public override inline fun sin(arg: Float): Float = kotlin.math.sin(arg)
public override inline fun cos(arg: Float): Float = kotlin.math.cos(arg)
public override inline fun tan(arg: Float): Float = kotlin.math.tan(arg)
public override inline fun acos(arg: Float): Float = kotlin.math.acos(arg)
public override inline fun asin(arg: Float): Float = kotlin.math.asin(arg)
public override inline fun atan(arg: Float): Float = kotlin.math.atan(arg)
override inline fun sinh(arg: Float): Float = kotlin.math.sinh(arg)
override inline fun cosh(arg: Float): Float = kotlin.math.cosh(arg)
override inline fun tanh(arg: Float): Float = kotlin.math.tanh(arg)
override inline fun asinh(arg: Float): Float = kotlin.math.asinh(arg)
override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg)
override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg)
public override inline fun sinh(arg: Float): Float = kotlin.math.sinh(arg)
public override inline fun cosh(arg: Float): Float = kotlin.math.cosh(arg)
public override inline fun tanh(arg: Float): Float = kotlin.math.tanh(arg)
public override inline fun asinh(arg: Float): Float = kotlin.math.asinh(arg)
public override inline fun acosh(arg: Float): Float = kotlin.math.acosh(arg)
public override inline fun atanh(arg: Float): Float = kotlin.math.atanh(arg)
override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat())
override inline fun exp(arg: Float): Float = kotlin.math.exp(arg)
override inline fun ln(arg: Float): Float = kotlin.math.ln(arg)
public override inline fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat())
public override inline fun exp(arg: Float): Float = kotlin.math.exp(arg)
public override inline fun ln(arg: Float): Float = kotlin.math.ln(arg)
override inline fun norm(arg: Float): Float = abs(arg)
public override inline fun norm(arg: Float): Float = abs(arg)
override inline fun Float.unaryMinus(): Float = -this
override inline fun Float.plus(b: Float): Float = this + b
override inline fun Float.minus(b: Float): Float = this - b
override inline fun Float.times(b: Float): Float = this * b
override inline fun Float.div(b: Float): Float = this / b
public override inline fun Float.unaryMinus(): Float = -this
public override inline fun Float.plus(b: Float): Float = this + b
public override inline fun Float.minus(b: Float): Float = this - b
public override inline fun Float.times(b: Float): Float = this * b
public override inline fun Float.div(b: Float): Float = this / b
}
/**
* A field for [Int] without boxing. Does not produce corresponding ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object IntRing : Ring<Int>, Norm<Int, Int> {
override val zero: Int
public object IntRing : Ring<Int>, Norm<Int, Int> {
public override val zero: Int
get() = 0
override val one: Int
public override val one: Int
get() = 1
override inline fun add(a: Int, b: Int): Int = a + b
override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a
public override inline fun add(a: Int, b: Int): Int = a + b
public override inline fun multiply(a: Int, k: Number): Int = k.toInt() * a
override inline fun multiply(a: Int, b: Int): Int = a * b
public override inline fun multiply(a: Int, b: Int): Int = a * b
override inline fun norm(arg: Int): Int = abs(arg)
public override inline fun norm(arg: Int): Int = abs(arg)
override inline fun Int.unaryMinus(): Int = -this
override inline fun Int.plus(b: Int): Int = this + b
override inline fun Int.minus(b: Int): Int = this - b
override inline fun Int.times(b: Int): Int = this * b
public override inline fun Int.unaryMinus(): Int = -this
public override inline fun Int.plus(b: Int): Int = this + b
public override inline fun Int.minus(b: Int): Int = this - b
public override inline fun Int.times(b: Int): Int = this * b
}
/**
* A field for [Short] without boxing. Does not produce appropriate ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object ShortRing : Ring<Short>, Norm<Short, Short> {
override val zero: Short
public object ShortRing : Ring<Short>, Norm<Short, Short> {
public override val zero: Short
get() = 0
override val one: Short
public override val one: Short
get() = 1
override inline fun add(a: Short, b: Short): Short = (a + b).toShort()
override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort()
public override inline fun add(a: Short, b: Short): Short = (a + b).toShort()
public override inline fun multiply(a: Short, k: Number): Short = (a * k.toShort()).toShort()
override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort()
public override inline fun multiply(a: Short, b: Short): Short = (a * b).toShort()
override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
public override fun norm(arg: Short): Short = if (arg > 0) arg else (-arg).toShort()
override inline fun Short.unaryMinus(): Short = (-this).toShort()
override inline fun Short.plus(b: Short): Short = (this + b).toShort()
override inline fun Short.minus(b: Short): Short = (this - b).toShort()
override inline fun Short.times(b: Short): Short = (this * b).toShort()
public override inline fun Short.unaryMinus(): Short = (-this).toShort()
public override inline fun Short.plus(b: Short): Short = (this + b).toShort()
public override inline fun Short.minus(b: Short): Short = (this - b).toShort()
public override inline fun Short.times(b: Short): Short = (this * b).toShort()
}
/**
* A field for [Byte] without boxing. Does not produce appropriate ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object ByteRing : Ring<Byte>, Norm<Byte, Byte> {
override val zero: Byte
public object ByteRing : Ring<Byte>, Norm<Byte, Byte> {
public override val zero: Byte
get() = 0
override val one: Byte
public override val one: Byte
get() = 1
override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte()
override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte()
public override inline fun add(a: Byte, b: Byte): Byte = (a + b).toByte()
public override inline fun multiply(a: Byte, k: Number): Byte = (a * k.toByte()).toByte()
override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte()
public override inline fun multiply(a: Byte, b: Byte): Byte = (a * b).toByte()
override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
public override fun norm(arg: Byte): Byte = if (arg > 0) arg else (-arg).toByte()
override inline fun Byte.unaryMinus(): Byte = (-this).toByte()
override inline fun Byte.plus(b: Byte): Byte = (this + b).toByte()
override inline fun Byte.minus(b: Byte): Byte = (this - b).toByte()
override inline fun Byte.times(b: Byte): Byte = (this * b).toByte()
public override inline fun Byte.unaryMinus(): Byte = (-this).toByte()
public override inline fun Byte.plus(b: Byte): Byte = (this + b).toByte()
public override inline fun Byte.minus(b: Byte): Byte = (this - b).toByte()
public override inline fun Byte.times(b: Byte): Byte = (this * b).toByte()
}
/**
* A field for [Double] without boxing. Does not produce appropriate ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object LongRing : Ring<Long>, Norm<Long, Long> {
override val zero: Long
public object LongRing : Ring<Long>, Norm<Long, Long> {
public override val zero: Long
get() = 0
override val one: Long
public override val one: Long
get() = 1
override inline fun add(a: Long, b: Long): Long = a + b
override inline fun multiply(a: Long, k: Number): Long = a * k.toLong()
public override inline fun add(a: Long, b: Long): Long = a + b
public override inline fun multiply(a: Long, k: Number): Long = a * k.toLong()
override inline fun multiply(a: Long, b: Long): Long = a * b
public override inline fun multiply(a: Long, b: Long): Long = a * b
override fun norm(arg: Long): Long = abs(arg)
public override fun norm(arg: Long): Long = abs(arg)
override inline fun Long.unaryMinus(): Long = (-this)
override inline fun Long.plus(b: Long): Long = (this + b)
override inline fun Long.minus(b: Long): Long = (this - b)
override inline fun Long.times(b: Long): Long = (this * b)
public override inline fun Long.unaryMinus(): Long = (-this)
public override inline fun Long.plus(b: Long): Long = (this + b)
public override inline fun Long.minus(b: Long): Long = (this - b)
public override inline fun Long.times(b: Long): Long = (this * b)
}

@ -5,230 +5,230 @@ package scientifik.kmath.operations
*
* @param T the type of element of this structure.
*/
interface TrigonometricOperations<T> : Algebra<T> {
public interface TrigonometricOperations<T> : Algebra<T> {
/**
* Computes the sine of [arg].
*/
fun sin(arg: T): T
public fun sin(arg: T): T
/**
* Computes the cosine of [arg].
*/
fun cos(arg: T): T
public fun cos(arg: T): T
/**
* Computes the tangent of [arg].
*/
fun tan(arg: T): T
public fun tan(arg: T): T
/**
* Computes the inverse sine of [arg].
*/
fun asin(arg: T): T
public fun asin(arg: T): T
/**
* Computes the inverse cosine of [arg].
*/
fun acos(arg: T): T
public fun acos(arg: T): T
/**
* Computes the inverse tangent of [arg].
*/
fun atan(arg: T): T
public fun atan(arg: T): T
companion object {
public companion object {
/**
* The identifier of sine.
*/
const val SIN_OPERATION: String = "sin"
public const val SIN_OPERATION: String = "sin"
/**
* The identifier of cosine.
*/
const val COS_OPERATION: String = "cos"
public const val COS_OPERATION: String = "cos"
/**
* The identifier of tangent.
*/
const val TAN_OPERATION: String = "tan"
public const val TAN_OPERATION: String = "tan"
/**
* The identifier of inverse sine.
*/
const val ASIN_OPERATION: String = "asin"
public const val ASIN_OPERATION: String = "asin"
/**
* The identifier of inverse cosine.
*/
const val ACOS_OPERATION: String = "acos"
public const val ACOS_OPERATION: String = "acos"
/**
* The identifier of inverse tangent.
*/
const val ATAN_OPERATION: String = "atan"
public const val ATAN_OPERATION: String = "atan"
}
}
/**
* Computes the sine of [arg].
*/
fun <T : MathElement<out TrigonometricOperations<T>>> sin(arg: T): T = arg.context.sin(arg)
public fun <T : MathElement<out TrigonometricOperations<T>>> sin(arg: T): T = arg.context.sin(arg)
/**
* Computes the cosine of [arg].
*/
fun <T : MathElement<out TrigonometricOperations<T>>> cos(arg: T): T = arg.context.cos(arg)
public fun <T : MathElement<out TrigonometricOperations<T>>> cos(arg: T): T = arg.context.cos(arg)
/**
* Computes the tangent of [arg].
*/
fun <T : MathElement<out TrigonometricOperations<T>>> tan(arg: T): T = arg.context.tan(arg)
public fun <T : MathElement<out TrigonometricOperations<T>>> tan(arg: T): T = arg.context.tan(arg)
/**
* Computes the inverse sine of [arg].
*/
fun <T : MathElement<out TrigonometricOperations<T>>> asin(arg: T): T = arg.context.asin(arg)
public fun <T : MathElement<out TrigonometricOperations<T>>> asin(arg: T): T = arg.context.asin(arg)
/**
* Computes the inverse cosine of [arg].
*/
fun <T : MathElement<out TrigonometricOperations<T>>> acos(arg: T): T = arg.context.acos(arg)
public fun <T : MathElement<out TrigonometricOperations<T>>> acos(arg: T): T = arg.context.acos(arg)
/**
* Computes the inverse tangent of [arg].
*/
fun <T : MathElement<out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg)
public fun <T : MathElement<out TrigonometricOperations<T>>> atan(arg: T): T = arg.context.atan(arg)
/**
* A container for hyperbolic trigonometric operations for specific type.
*
* @param T the type of element of this structure.
*/
interface HyperbolicOperations<T> : Algebra<T> {
public interface HyperbolicOperations<T> : Algebra<T> {
/**
* Computes the hyperbolic sine of [arg].
*/
fun sinh(arg: T): T
public fun sinh(arg: T): T
/**
* Computes the hyperbolic cosine of [arg].
*/
fun cosh(arg: T): T
public fun cosh(arg: T): T
/**
* Computes the hyperbolic tangent of [arg].
*/
fun tanh(arg: T): T
public fun tanh(arg: T): T
/**
* Computes the inverse hyperbolic sine of [arg].
*/
fun asinh(arg: T): T
public fun asinh(arg: T): T
/**
* Computes the inverse hyperbolic cosine of [arg].
*/
fun acosh(arg: T): T
public fun acosh(arg: T): T
/**
* Computes the inverse hyperbolic tangent of [arg].
*/
fun atanh(arg: T): T
public fun atanh(arg: T): T
companion object {
public companion object {
/**
* The identifier of hyperbolic sine.
*/
const val SINH_OPERATION: String = "sinh"
public const val SINH_OPERATION: String = "sinh"
/**
* The identifier of hyperbolic cosine.
*/
const val COSH_OPERATION: String = "cosh"
public const val COSH_OPERATION: String = "cosh"
/**
* The identifier of hyperbolic tangent.
*/
const val TANH_OPERATION: String = "tanh"
public const val TANH_OPERATION: String = "tanh"
/**
* The identifier of inverse hyperbolic sine.
*/
const val ASINH_OPERATION: String = "asinh"
public const val ASINH_OPERATION: String = "asinh"
/**
* The identifier of inverse hyperbolic cosine.
*/
const val ACOSH_OPERATION: String = "acosh"
public const val ACOSH_OPERATION: String = "acosh"
/**
* The identifier of inverse hyperbolic tangent.
*/
const val ATANH_OPERATION: String = "atanh"
public const val ATANH_OPERATION: String = "atanh"
}
}
/**
* Computes the hyperbolic sine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
public fun <T : MathElement<out HyperbolicOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
/**
* Computes the hyperbolic cosine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
public fun <T : MathElement<out HyperbolicOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
/**
* Computes the hyperbolic tangent of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
public fun <T : MathElement<out HyperbolicOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
/**
* Computes the inverse hyperbolic sine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
public fun <T : MathElement<out HyperbolicOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
/**
* Computes the inverse hyperbolic cosine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
public fun <T : MathElement<out HyperbolicOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
/**
* Computes the inverse hyperbolic tangent of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
public fun <T : MathElement<out HyperbolicOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
/**
* A context extension to include power operations based on exponentiation.
*
* @param T the type of element of this structure.
*/
interface PowerOperations<T> : Algebra<T> {
public interface PowerOperations<T> : Algebra<T> {
/**
* Raises [arg] to the power [pow].
*/
fun power(arg: T, pow: Number): T
public fun power(arg: T, pow: Number): T
/**
* Computes the square root of the value [arg].
*/
fun sqrt(arg: T): T = power(arg, 0.5)
public fun sqrt(arg: T): T = power(arg, 0.5)
/**
* Raises this value to the power [pow].
*/
infix fun T.pow(pow: Number): T = power(this, pow)
public infix fun T.pow(pow: Number): T = power(this, pow)
companion object {
public companion object {
/**
* The identifier of exponentiation.
*/
const val POW_OPERATION: String = "pow"
public const val POW_OPERATION: String = "pow"
/**
* The identifier of square root.
*/
const val SQRT_OPERATION: String = "sqrt"
public const val SQRT_OPERATION: String = "sqrt"
}
}
@ -239,56 +239,56 @@ interface PowerOperations<T> : Algebra<T> {
* @param power the exponent.
* @return the base raised to the power.
*/
infix fun <T : MathElement<out PowerOperations<T>>> T.pow(power: Double): T = context.power(this, power)
public infix fun <T : MathElement<out PowerOperations<T>>> T.pow(power: Double): T = context.power(this, power)
/**
* Computes the square root of the value [arg].
*/
fun <T : MathElement<out PowerOperations<T>>> sqrt(arg: T): T = arg pow 0.5
public fun <T : MathElement<out PowerOperations<T>>> sqrt(arg: T): T = arg pow 0.5
/**
* Computes the square of the value [arg].
*/
fun <T : MathElement<out PowerOperations<T>>> sqr(arg: T): T = arg pow 2.0
public fun <T : MathElement<out PowerOperations<T>>> sqr(arg: T): T = arg pow 2.0
/**
* A container for operations related to `exp` and `ln` functions.
*
* @param T the type of element of this structure.
*/
interface ExponentialOperations<T> : Algebra<T> {
public interface ExponentialOperations<T> : Algebra<T> {
/**
* Computes Euler's number `e` raised to the power of the value [arg].
*/
fun exp(arg: T): T
public fun exp(arg: T): T
/**
* Computes the natural logarithm (base `e`) of the value [arg].
*/
fun ln(arg: T): T
public fun ln(arg: T): T
companion object {
public companion object {
/**
* The identifier of exponential function.
*/
const val EXP_OPERATION: String = "exp"
public const val EXP_OPERATION: String = "exp"
/**
* The identifier of natural logarithm.
*/
const val LN_OPERATION: String = "ln"
public const val LN_OPERATION: String = "ln"
}
}
/**
* The identifier of exponential function.
*/
fun <T : MathElement<out ExponentialOperations<T>>> exp(arg: T): T = arg.context.exp(arg)
public fun <T : MathElement<out ExponentialOperations<T>>> exp(arg: T): T = arg.context.exp(arg)
/**
* The identifier of natural logarithm.
*/
fun <T : MathElement<out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
public fun <T : MathElement<out ExponentialOperations<T>>> ln(arg: T): T = arg.context.ln(arg)
/**
* A container for norm functional on element.
@ -296,14 +296,14 @@ fun <T : MathElement<out ExponentialOperations<T>>> ln(arg: T): T = arg.context.
* @param T the type of element having norm defined.
* @param R the type of norm.
*/
interface Norm<in T : Any, out R> {
public interface Norm<in T : Any, out R> {
/**
* Computes the norm of [arg] (i.e. absolute value or vector length).
*/
fun norm(arg: T): R
public fun norm(arg: T): R
}
/**
* Computes the norm of [arg] (i.e. absolute value or vector length).
*/
fun <T : MathElement<out Norm<T, R>>, R> norm(arg: T): R = arg.context.norm(arg)
public fun <T : MathElement<out Norm<T, R>>, R> norm(arg: T): R = arg.context.norm(arg)

@ -3,28 +3,28 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.Field
import scientifik.kmath.operations.FieldElement
class BoxingNDField<T, F : Field<T>>(
override val shape: IntArray,
override val elementContext: F,
val bufferFactory: BufferFactory<T>
public class BoxingNDField<T, F : Field<T>>(
public override val shape: IntArray,
public override val elementContext: F,
public val bufferFactory: BufferFactory<T>
) : BufferedNDField<T, F> {
override val zero: BufferedNDFieldElement<T, F> by lazy { produce { zero } }
override val one: BufferedNDFieldElement<T, F> by lazy { produce { one } }
override val strides: Strides = DefaultStrides(shape)
public override val zero: BufferedNDFieldElement<T, F> by lazy { produce { zero } }
public override val one: BufferedNDFieldElement<T, F> by lazy { produce { one } }
public override val strides: Strides = DefaultStrides(shape)
fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer<T> =
public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer<T> =
bufferFactory(size, initializer)
override fun check(vararg elements: NDBuffer<T>) {
public override fun check(vararg elements: NDBuffer<T>) {
check(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" }
}
override fun produce(initializer: F.(IntArray) -> T): BufferedNDFieldElement<T, F> =
public override fun produce(initializer: F.(IntArray) -> T): BufferedNDFieldElement<T, F> =
BufferedNDFieldElement(
this,
buildBuffer(strides.linearSize) { offset -> elementContext.initializer(strides.index(offset)) })
override fun map(arg: NDBuffer<T>, transform: F.(T) -> T): BufferedNDFieldElement<T, F> {
public override fun map(arg: NDBuffer<T>, transform: F.(T) -> T): BufferedNDFieldElement<T, F> {
check(arg)
return BufferedNDFieldElement(
@ -36,7 +36,7 @@ class BoxingNDField<T, F : Field<T>>(
}
override fun mapIndexed(
public override fun mapIndexed(
arg: NDBuffer<T>,
transform: F.(index: IntArray, T) -> T
): BufferedNDFieldElement<T, F> {
@ -55,7 +55,7 @@ class BoxingNDField<T, F : Field<T>>(
// return BufferedNDFieldElement(this, buffer)
}
override fun combine(
public override fun combine(
a: NDBuffer<T>,
b: NDBuffer<T>,
transform: F.(T, T) -> T
@ -66,11 +66,11 @@ class BoxingNDField<T, F : Field<T>>(
buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) })
}
override fun NDBuffer<T>.toElement(): FieldElement<NDBuffer<T>, *, out BufferedNDField<T, F>> =
public override fun NDBuffer<T>.toElement(): FieldElement<NDBuffer<T>, *, out BufferedNDField<T, F>> =
BufferedNDFieldElement(this@BoxingNDField, buffer)
}
inline fun <T : Any, F : Field<T>, R> F.nd(
public inline fun <T : Any, F : Field<T>, R> F.nd(
noinline bufferFactory: BufferFactory<T>,
vararg shape: Int,
action: NDField<T, F, *>.() -> R

@ -3,16 +3,16 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.Ring
import scientifik.kmath.operations.RingElement
class BoxingNDRing<T, R : Ring<T>>(
public class BoxingNDRing<T, R : Ring<T>>(
override val shape: IntArray,
override val elementContext: R,
val bufferFactory: BufferFactory<T>
public val bufferFactory: BufferFactory<T>
) : BufferedNDRing<T, R> {
override val strides: Strides = DefaultStrides(shape)
override val zero: BufferedNDRingElement<T, R> by lazy { produce { zero } }
override val one: BufferedNDRingElement<T, R> by lazy { produce { one } }
fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer<T> = bufferFactory(size, initializer)
public fun buildBuffer(size: Int, initializer: (Int) -> T): Buffer<T> = bufferFactory(size, initializer)
override fun check(vararg elements: NDBuffer<T>) {
require(elements.all { it.strides == strides }) { "Element strides are not the same as context strides" }
@ -59,6 +59,7 @@ class BoxingNDRing<T, R : Ring<T>>(
transform: R.(T, T) -> T
): BufferedNDRingElement<T, R> {
check(a, b)
return BufferedNDRingElement(
this,
buildBuffer(strides.linearSize) { offset -> elementContext.transform(a.buffer[offset], b.buffer[offset]) })

@ -5,24 +5,23 @@ import kotlin.reflect.KClass
/**
* A context that allows to operate on a [MutableBuffer] as on 2d array
*/
class BufferAccessor2D<T : Any>(val type: KClass<T>, val rowNum: Int, val colNum: Int) {
operator fun Buffer<T>.get(i: Int, j: Int): T = get(i + colNum * j)
public class BufferAccessor2D<T : Any>(public val type: KClass<T>, public val rowNum: Int, public val colNum: Int) {
public operator fun Buffer<T>.get(i: Int, j: Int): T = get(i + colNum * j)
operator fun MutableBuffer<T>.set(i: Int, j: Int, value: T) {
public operator fun MutableBuffer<T>.set(i: Int, j: Int, value: T) {
set(i + colNum * j, value)
}
inline fun create(init: (i: Int, j: Int) -> T): MutableBuffer<T> =
public inline fun create(init: (i: Int, j: Int) -> T): MutableBuffer<T> =
MutableBuffer.auto(type, rowNum * colNum) { offset -> init(offset / colNum, offset % colNum) }
fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] }
public fun create(mat: Structure2D<T>): MutableBuffer<T> = create { i, j -> mat[i, j] }
//TODO optimize wrapper
fun MutableBuffer<T>.collect(): Structure2D<T> =
public fun MutableBuffer<T>.collect(): Structure2D<T> =
NDStructure.auto(type, rowNum, colNum) { (i, j) -> get(i, j) }.as2D()
inner class Row(val buffer: MutableBuffer<T>, val rowIndex: Int) : MutableBuffer<T> {
public inner class Row(public val buffer: MutableBuffer<T>, public val rowIndex: Int) : MutableBuffer<T> {
override val size: Int get() = colNum
override operator fun get(index: Int): T = buffer[rowIndex, index]
@ -39,5 +38,5 @@ class BufferAccessor2D<T : Any>(val type: KClass<T>, val rowNum: Int, val colNum
/**
* Get row
*/
fun MutableBuffer<T>.row(i: Int): Row = Row(this, i)
public fun MutableBuffer<T>.row(i: Int): Row = Row(this, i)
}

@ -2,10 +2,10 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.*
interface BufferedNDAlgebra<T, C> : NDAlgebra<T, C, NDBuffer<T>> {
val strides: Strides
public interface BufferedNDAlgebra<T, C> : NDAlgebra<T, C, NDBuffer<T>> {
public val strides: Strides
override fun check(vararg elements: NDBuffer<T>): Unit =
public override fun check(vararg elements: NDBuffer<T>): Unit =
require(elements.all { it.strides == strides }) { ("Strides mismatch") }
/**
@ -15,29 +15,27 @@ interface BufferedNDAlgebra<T, C> : NDAlgebra<T, C, NDBuffer<T>> {
*
* If the argument is [NDBuffer] with different strides structure, the new element will be produced.
*/
fun NDStructure<T>.toBuffer(): NDBuffer<T> {
return if (this is NDBuffer<T> && this.strides == this@BufferedNDAlgebra.strides) {
public fun NDStructure<T>.toBuffer(): NDBuffer<T> =
if (this is NDBuffer<T> && this.strides == this@BufferedNDAlgebra.strides)
this
} else {
produce { index -> get(index) }
}
}
else
produce { index -> this@toBuffer[index] }
/**
* Convert a buffer to element of this algebra
*/
fun NDBuffer<T>.toElement(): MathElement<out BufferedNDAlgebra<T, C>>
public fun NDBuffer<T>.toElement(): MathElement<out BufferedNDAlgebra<T, C>>
}
interface BufferedNDSpace<T, S : Space<T>> : NDSpace<T, S, NDBuffer<T>>, BufferedNDAlgebra<T, S> {
override fun NDBuffer<T>.toElement(): SpaceElement<NDBuffer<T>, *, out BufferedNDSpace<T, S>>
public interface BufferedNDSpace<T, S : Space<T>> : NDSpace<T, S, NDBuffer<T>>, BufferedNDAlgebra<T, S> {
public override fun NDBuffer<T>.toElement(): SpaceElement<NDBuffer<T>, *, out BufferedNDSpace<T, S>>
}
interface BufferedNDRing<T, R : Ring<T>> : NDRing<T, R, NDBuffer<T>>, BufferedNDSpace<T, R> {
public interface BufferedNDRing<T, R : Ring<T>> : NDRing<T, R, NDBuffer<T>>, BufferedNDSpace<T, R> {
override fun NDBuffer<T>.toElement(): RingElement<NDBuffer<T>, *, out BufferedNDRing<T, R>>
}
interface BufferedNDField<T, F : Field<T>> : NDField<T, F, NDBuffer<T>>, BufferedNDRing<T, F> {
public interface BufferedNDField<T, F : Field<T>> : NDField<T, F, NDBuffer<T>>, BufferedNDRing<T, F> {
override fun NDBuffer<T>.toElement(): FieldElement<NDBuffer<T>, *, out BufferedNDField<T, F>>
}

@ -5,7 +5,7 @@ import scientifik.kmath.operations.*
/**
* Base class for an element with context, containing strides
*/
abstract class BufferedNDElement<T, C> : NDBuffer<T>(), NDElement<T, C, NDBuffer<T>> {
public abstract class BufferedNDElement<T, C> : NDBuffer<T>(), NDElement<T, C, NDBuffer<T>> {
abstract override val context: BufferedNDAlgebra<T, C>
override val strides: Strides get() = context.strides
@ -13,7 +13,7 @@ abstract class BufferedNDElement<T, C> : NDBuffer<T>(), NDElement<T, C, NDBuffer
override val shape: IntArray get() = context.shape
}
class BufferedNDSpaceElement<T, S : Space<T>>(
public class BufferedNDSpaceElement<T, S : Space<T>>(
override val context: BufferedNDSpace<T, S>,
override val buffer: Buffer<T>
) : BufferedNDElement<T, S>(), SpaceElement<NDBuffer<T>, BufferedNDSpaceElement<T, S>, BufferedNDSpace<T, S>> {
@ -26,7 +26,7 @@ class BufferedNDSpaceElement<T, S : Space<T>>(
}
}
class BufferedNDRingElement<T, R : Ring<T>>(
public class BufferedNDRingElement<T, R : Ring<T>>(
override val context: BufferedNDRing<T, R>,
override val buffer: Buffer<T>
) : BufferedNDElement<T, R>(), RingElement<NDBuffer<T>, BufferedNDRingElement<T, R>, BufferedNDRing<T, R>> {
@ -38,7 +38,7 @@ class BufferedNDRingElement<T, R : Ring<T>>(
}
}
class BufferedNDFieldElement<T, F : Field<T>>(
public class BufferedNDFieldElement<T, F : Field<T>>(
override val context: BufferedNDField<T, F>,
override val buffer: Buffer<T>
) : BufferedNDElement<T, F>(), FieldElement<NDBuffer<T>, BufferedNDFieldElement<T, F>, BufferedNDField<T, F>> {
@ -54,7 +54,7 @@ class BufferedNDFieldElement<T, F : Field<T>>(
/**
* Element by element application of any operation on elements to the whole array. Just like in numpy.
*/
operator fun <T : Any, F : Field<T>> Function1<T, T>.invoke(ndElement: BufferedNDElement<T, F>): MathElement<out BufferedNDAlgebra<T, F>> =
public operator fun <T : Any, F : Field<T>> Function1<T, T>.invoke(ndElement: BufferedNDElement<T, F>): MathElement<out BufferedNDAlgebra<T, F>> =
ndElement.context.run { map(ndElement) { invoke(it) }.toElement() }
/* plus and minus */
@ -62,13 +62,13 @@ operator fun <T : Any, F : Field<T>> Function1<T, T>.invoke(ndElement: BufferedN
/**
* Summation operation for [BufferedNDElement] and single element
*/
operator fun <T : Any, F : Space<T>> BufferedNDElement<T, F>.plus(arg: T): NDElement<T, F, NDBuffer<T>> =
public operator fun <T : Any, F : Space<T>> BufferedNDElement<T, F>.plus(arg: T): NDElement<T, F, NDBuffer<T>> =
context.map(this) { it + arg }.wrap()
/**
* Subtraction operation between [BufferedNDElement] and single element
*/
operator fun <T : Any, F : Space<T>> BufferedNDElement<T, F>.minus(arg: T): NDElement<T, F, NDBuffer<T>> =
public operator fun <T : Any, F : Space<T>> BufferedNDElement<T, F>.minus(arg: T): NDElement<T, F, NDBuffer<T>> =
context.map(this) { it - arg }.wrap()
/* prod and div */
@ -76,11 +76,11 @@ operator fun <T : Any, F : Space<T>> BufferedNDElement<T, F>.minus(arg: T): NDEl
/**
* Product operation for [BufferedNDElement] and single element
*/
operator fun <T : Any, F : Ring<T>> BufferedNDElement<T, F>.times(arg: T): NDElement<T, F, NDBuffer<T>> =
public operator fun <T : Any, F : Ring<T>> BufferedNDElement<T, F>.times(arg: T): NDElement<T, F, NDBuffer<T>> =
context.map(this) { it * arg }.wrap()
/**
* Division operation between [BufferedNDElement] and single element
*/
operator fun <T : Any, F : Field<T>> BufferedNDElement<T, F>.div(arg: T): NDElement<T, F, NDBuffer<T>> =
public operator fun <T : Any, F : Field<T>> BufferedNDElement<T, F>.div(arg: T): NDElement<T, F, NDBuffer<T>> =
context.map(this) { it / arg }.wrap()

@ -2,8 +2,6 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.Complex
import scientifik.kmath.operations.complex
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.reflect.KClass
/**
@ -11,44 +9,44 @@ import kotlin.reflect.KClass
*
* @param T the type of buffer.
*/
typealias BufferFactory<T> = (Int, (Int) -> T) -> Buffer<T>
public typealias BufferFactory<T> = (Int, (Int) -> T) -> Buffer<T>
/**
* Function that produces [MutableBuffer] from its size and function that supplies values.
*
* @param T the type of buffer.
*/
typealias MutableBufferFactory<T> = (Int, (Int) -> T) -> MutableBuffer<T>
public typealias MutableBufferFactory<T> = (Int, (Int) -> T) -> MutableBuffer<T>
/**
* A generic immutable random-access structure for both primitives and objects.
*
* @param T the type of elements contained in the buffer.
*/
interface Buffer<T> {
public interface Buffer<T> {
/**
* The size of this buffer.
*/
val size: Int
public val size: Int
/**
* Gets element at given index.
*/
operator fun get(index: Int): T
public operator fun get(index: Int): T
/**
* Iterates over all elements.
*/
operator fun iterator(): Iterator<T>
public operator fun iterator(): Iterator<T>
/**
* Checks content equality with another buffer.
*/
fun contentEquals(other: Buffer<*>): Boolean =
public fun contentEquals(other: Buffer<*>): Boolean =
asSequence().mapIndexed { index, value -> value == other[index] }.all { it }
companion object {
inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer {
public companion object {
public inline fun real(size: Int, initializer: (Int) -> Double): RealBuffer {
val array = DoubleArray(size) { initializer(it) }
return RealBuffer(array)
}
@ -56,10 +54,11 @@ interface Buffer<T> {
/**
* Create a boxing buffer of given type
*/
inline fun <T> boxing(size: Int, initializer: (Int) -> T): Buffer<T> = ListBuffer(List(size, initializer))
public inline fun <T> boxing(size: Int, initializer: (Int) -> T): Buffer<T> =
ListBuffer(List(size, initializer))
@Suppress("UNCHECKED_CAST")
inline fun <T : Any> auto(type: KClass<T>, size: Int, crossinline initializer: (Int) -> T): Buffer<T> {
public inline fun <T : Any> auto(type: KClass<T>, size: Int, crossinline initializer: (Int) -> T): Buffer<T> {
//TODO add resolution based on Annotation or companion resolution
return when (type) {
Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as Buffer<T>
@ -75,7 +74,7 @@ interface Buffer<T> {
* Create most appropriate immutable buffer for given type avoiding boxing wherever possible
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> auto(size: Int, crossinline initializer: (Int) -> T): Buffer<T> =
public inline fun <reified T : Any> auto(size: Int, crossinline initializer: (Int) -> T): Buffer<T> =
auto(T::class, size, initializer)
}
}
@ -83,43 +82,43 @@ interface Buffer<T> {
/**
* Creates a sequence that returns all elements from this [Buffer].
*/
fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
/**
* Creates an iterable that returns all elements from this [Buffer].
*/
fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
/**
* Returns an [IntRange] of the valid indices for this [Buffer].
*/
val Buffer<*>.indices: IntRange get() = 0 until size
public val Buffer<*>.indices: IntRange get() = 0 until size
/**
* A generic mutable random-access structure for both primitives and objects.
*
* @param T the type of elements contained in the buffer.
*/
interface MutableBuffer<T> : Buffer<T> {
public interface MutableBuffer<T> : Buffer<T> {
/**
* Sets the array element at the specified [index] to the specified [value].
*/
operator fun set(index: Int, value: T)
public operator fun set(index: Int, value: T)
/**
* Returns a shallow copy of the buffer.
*/
fun copy(): MutableBuffer<T>
public fun copy(): MutableBuffer<T>
companion object {
public companion object {
/**
* Create a boxing mutable buffer of given type
*/
inline fun <T> boxing(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
public inline fun <T> boxing(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
MutableListBuffer(MutableList(size, initializer))
@Suppress("UNCHECKED_CAST")
inline fun <T : Any> auto(type: KClass<out T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
public inline fun <T : Any> auto(type: KClass<out T>, size: Int, initializer: (Int) -> T): MutableBuffer<T> =
when (type) {
Double::class -> RealBuffer(DoubleArray(size) { initializer(it) as Double }) as MutableBuffer<T>
Short::class -> ShortBuffer(ShortArray(size) { initializer(it) as Short }) as MutableBuffer<T>
@ -132,12 +131,11 @@ interface MutableBuffer<T> : Buffer<T> {
* Create most appropriate mutable buffer for given type avoiding boxing wherever possible
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> auto(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
public inline fun <reified T : Any> auto(size: Int, initializer: (Int) -> T): MutableBuffer<T> =
auto(T::class, size, initializer)
val real: MutableBufferFactory<Double> = { size: Int, initializer: (Int) -> Double ->
RealBuffer(DoubleArray(size) { initializer(it) })
}
public val real: MutableBufferFactory<Double> =
{ size, initializer -> RealBuffer(DoubleArray(size) { initializer(it) }) }
}
}
@ -147,7 +145,7 @@ interface MutableBuffer<T> : Buffer<T> {
* @param T the type of elements contained in the buffer.
* @property list The underlying list.
*/
inline class ListBuffer<T>(val list: List<T>) : Buffer<T> {
public inline class ListBuffer<T>(public val list: List<T>) : Buffer<T> {
override val size: Int
get() = list.size
@ -158,7 +156,7 @@ inline class ListBuffer<T>(val list: List<T>) : Buffer<T> {
/**
* Returns an [ListBuffer] that wraps the original list.
*/
fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
public fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
/**
* Creates a new [ListBuffer] with the specified [size], where each element is calculated by calling the specified
@ -167,10 +165,7 @@ fun <T> List<T>.asBuffer(): ListBuffer<T> = ListBuffer(this)
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an array element given its index.
*/
inline fun <T> ListBuffer(size: Int, init: (Int) -> T): ListBuffer<T> {
contract { callsInPlace(init) }
return List(size, init).asBuffer()
}
public inline fun <T> ListBuffer(size: Int, init: (Int) -> T): ListBuffer<T> = List(size, init).asBuffer()
/**
* [MutableBuffer] implementation over [MutableList].
@ -178,7 +173,7 @@ inline fun <T> ListBuffer(size: Int, init: (Int) -> T): ListBuffer<T> {
* @param T the type of elements contained in the buffer.
* @property list The underlying list.
*/
inline class MutableListBuffer<T>(val list: MutableList<T>) : MutableBuffer<T> {
public inline class MutableListBuffer<T>(public val list: MutableList<T>) : MutableBuffer<T> {
override val size: Int
get() = list.size
@ -198,7 +193,7 @@ inline class MutableListBuffer<T>(val list: MutableList<T>) : MutableBuffer<T> {
* @param T the type of elements contained in the buffer.
* @property array The underlying array.
*/
class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
public class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
// Can't inline because array is invariant
override val size: Int
get() = array.size
@ -216,7 +211,7 @@ class ArrayBuffer<T>(private val array: Array<T>) : MutableBuffer<T> {
/**
* Returns an [ArrayBuffer] that wraps the original array.
*/
fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
public fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
/**
* Immutable wrapper for [MutableBuffer].
@ -224,7 +219,7 @@ fun <T> Array<T>.asBuffer(): ArrayBuffer<T> = ArrayBuffer(this)
* @param T the type of elements contained in the buffer.
* @property buffer The underlying buffer.
*/
inline class ReadOnlyBuffer<T>(val buffer: MutableBuffer<T>) : Buffer<T> {
public inline class ReadOnlyBuffer<T>(public val buffer: MutableBuffer<T>) : Buffer<T> {
override val size: Int get() = buffer.size
override operator fun get(index: Int): T = buffer[index]
@ -238,7 +233,7 @@ inline class ReadOnlyBuffer<T>(val buffer: MutableBuffer<T>) : Buffer<T> {
*
* @param T the type of elements provided by the buffer.
*/
class VirtualBuffer<T>(override val size: Int, private val generator: (Int) -> T) : Buffer<T> {
public class VirtualBuffer<T>(override val size: Int, private val generator: (Int) -> T) : Buffer<T> {
override operator fun get(index: Int): T {
if (index < 0 || index >= size) throw IndexOutOfBoundsException("Expected index from 0 to ${size - 1}, but found $index")
return generator(index)
@ -258,14 +253,14 @@ class VirtualBuffer<T>(override val size: Int, private val generator: (Int) -> T
/**
* Convert this buffer to read-only buffer.
*/
fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
public fun <T> Buffer<T>.asReadOnly(): Buffer<T> = if (this is MutableBuffer) ReadOnlyBuffer(this) else this
/**
* Typealias for buffer transformations.
*/
typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
public typealias BufferTransform<T, R> = (Buffer<T>) -> Buffer<R>
/**
* Typealias for buffer transformations with suspend function.
*/
typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>
public typealias SuspendBufferTransform<T, R> = suspend (Buffer<T>) -> Buffer<R>

@ -4,16 +4,15 @@ import scientifik.kmath.operations.Complex
import scientifik.kmath.operations.ComplexField
import scientifik.kmath.operations.FieldElement
import scientifik.kmath.operations.complex
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
typealias ComplexNDElement = BufferedNDFieldElement<Complex, ComplexField>
public typealias ComplexNDElement = BufferedNDFieldElement<Complex, ComplexField>
/**
* An optimized nd-field for complex numbers
*/
class ComplexNDField(override val shape: IntArray) :
public class ComplexNDField(override val shape: IntArray) :
BufferedNDField<Complex, ComplexField>,
ExtendedNDField<Complex, ComplexField, NDBuffer<Complex>> {
@ -22,7 +21,7 @@ class ComplexNDField(override val shape: IntArray) :
override val zero: ComplexNDElement by lazy { produce { zero } }
override val one: ComplexNDElement by lazy { produce { one } }
inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer<Complex> =
public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Complex): Buffer<Complex> =
Buffer.complex(size) { initializer(it) }
/**
@ -98,7 +97,7 @@ class ComplexNDField(override val shape: IntArray) :
/**
* Fast element production using function inlining
*/
inline fun BufferedNDField<Complex, ComplexField>.produceInline(crossinline initializer: ComplexField.(Int) -> Complex): ComplexNDElement {
public inline fun BufferedNDField<Complex, ComplexField>.produceInline(initializer: ComplexField.(Int) -> Complex): ComplexNDElement {
val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.initializer(offset) }
return BufferedNDFieldElement(this, buffer)
}
@ -106,14 +105,13 @@ inline fun BufferedNDField<Complex, ComplexField>.produceInline(crossinline init
/**
* Map one [ComplexNDElement] using function with indices.
*/
inline fun ComplexNDElement.mapIndexed(crossinline transform: ComplexField.(index: IntArray, Complex) -> Complex): ComplexNDElement =
public inline fun ComplexNDElement.mapIndexed(transform: ComplexField.(index: IntArray, Complex) -> Complex): ComplexNDElement =
context.produceInline { offset -> transform(strides.index(offset), buffer[offset]) }
/**
* Map one [ComplexNDElement] using function without indices.
*/
inline fun ComplexNDElement.map(crossinline transform: ComplexField.(Complex) -> Complex): ComplexNDElement {
contract { callsInPlace(transform) }
public inline fun ComplexNDElement.map(transform: ComplexField.(Complex) -> Complex): ComplexNDElement {
val buffer = Buffer.complex(strides.linearSize) { offset -> ComplexField.transform(buffer[offset]) }
return BufferedNDFieldElement(context, buffer)
}
@ -121,38 +119,35 @@ inline fun ComplexNDElement.map(crossinline transform: ComplexField.(Complex) ->
/**
* Element by element application of any operation on elements to the whole array. Just like in numpy
*/
operator fun Function1<Complex, Complex>.invoke(ndElement: ComplexNDElement): ComplexNDElement =
public operator fun Function1<Complex, Complex>.invoke(ndElement: ComplexNDElement): ComplexNDElement =
ndElement.map { this@invoke(it) }
/* plus and minus */
/**
* Summation operation for [BufferedNDElement] and single element
*/
operator fun ComplexNDElement.plus(arg: Complex): ComplexNDElement = map { it + arg }
public operator fun ComplexNDElement.plus(arg: Complex): ComplexNDElement = map { it + arg }
/**
* Subtraction operation between [BufferedNDElement] and single element
*/
operator fun ComplexNDElement.minus(arg: Complex): ComplexNDElement =
map { it - arg }
public operator fun ComplexNDElement.minus(arg: Complex): ComplexNDElement = map { it - arg }
operator fun ComplexNDElement.plus(arg: Double): ComplexNDElement =
map { it + arg }
public operator fun ComplexNDElement.plus(arg: Double): ComplexNDElement = map { it + arg }
public operator fun ComplexNDElement.minus(arg: Double): ComplexNDElement = map { it - arg }
operator fun ComplexNDElement.minus(arg: Double): ComplexNDElement =
map { it - arg }
public fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape)
fun NDField.Companion.complex(vararg shape: Int): ComplexNDField = ComplexNDField(shape)
fun NDElement.Companion.complex(vararg shape: Int, initializer: ComplexField.(IntArray) -> Complex): ComplexNDElement =
NDField.complex(*shape).produce(initializer)
public fun NDElement.Companion.complex(
vararg shape: Int,
initializer: ComplexField.(IntArray) -> Complex
): ComplexNDElement = NDField.complex(*shape).produce(initializer)
/**
* Produce a context for n-dimensional operations inside this real field
*/
inline fun <R> ComplexField.nd(vararg shape: Int, action: ComplexNDField.() -> R): R {
public inline fun <R> ComplexField.nd(vararg shape: Int, action: ComplexNDField.() -> R): R {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
return NDField.complex(*shape).action()
}

@ -9,7 +9,7 @@ import scientifik.kmath.operations.ExtendedField
* @param N the type of ND structure.
* @param F the extended field of structure elements.
*/
interface ExtendedNDField<T : Any, F : ExtendedField<T>, N : NDStructure<T>> : NDField<T, F, N>, ExtendedField<N>
public interface ExtendedNDField<T : Any, F : ExtendedField<T>, N : NDStructure<T>> : NDField<T, F, N>, ExtendedField<N>
///**
// * NDField that supports [ExtendedField] operations on its elements

@ -1,7 +1,5 @@
package scientifik.kmath.structures
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.experimental.and
/**
@ -9,7 +7,7 @@ import kotlin.experimental.and
*
* @property mask bit mask value of this flag.
*/
enum class ValueFlag(val mask: Byte) {
public enum class ValueFlag(public val mask: Byte) {
/**
* Reports the value is NaN.
*/
@ -34,23 +32,23 @@ enum class ValueFlag(val mask: Byte) {
/**
* A buffer with flagged values.
*/
interface FlaggedBuffer<T> : Buffer<T> {
fun getFlag(index: Int): Byte
public interface FlaggedBuffer<T> : Buffer<T> {
public fun getFlag(index: Int): Byte
}
/**
* The value is valid if all flags are down
*/
fun FlaggedBuffer<*>.isValid(index: Int): Boolean = getFlag(index) != 0.toByte()
public fun FlaggedBuffer<*>.isValid(index: Int): Boolean = getFlag(index) != 0.toByte()
fun FlaggedBuffer<*>.hasFlag(index: Int, flag: ValueFlag): Boolean = (getFlag(index) and flag.mask) != 0.toByte()
public fun FlaggedBuffer<*>.hasFlag(index: Int, flag: ValueFlag): Boolean = (getFlag(index) and flag.mask) != 0.toByte()
fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, ValueFlag.MISSING)
public fun FlaggedBuffer<*>.isMissing(index: Int): Boolean = hasFlag(index, ValueFlag.MISSING)
/**
* A real buffer which supports flags for each value like NaN or Missing
*/
class FlaggedRealBuffer(val values: DoubleArray, val flags: ByteArray) : FlaggedBuffer<Double?>, Buffer<Double?> {
public class FlaggedRealBuffer(public val values: DoubleArray, public val flags: ByteArray) : FlaggedBuffer<Double?>, Buffer<Double?> {
init {
require(values.size == flags.size) { "Values and flags must have the same dimensions" }
}
@ -66,9 +64,7 @@ class FlaggedRealBuffer(val values: DoubleArray, val flags: ByteArray) : Flagged
}.iterator()
}
inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) {
contract { callsInPlace(block) }
public inline fun FlaggedRealBuffer.forEachValid(block: (Double) -> Unit) {
indices
.asSequence()
.filter(::isValid)

@ -8,7 +8,7 @@ import kotlin.contracts.contract
*
* @property array the underlying array.
*/
inline class FloatBuffer(val array: FloatArray) : MutableBuffer<Float> {
public inline class FloatBuffer(public val array: FloatArray) : MutableBuffer<Float> {
override val size: Int get() = array.size
override operator fun get(index: Int): Float = array[index]
@ -30,20 +30,17 @@ inline class FloatBuffer(val array: FloatArray) : MutableBuffer<Float> {
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an buffer element given its index.
*/
inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer {
contract { callsInPlace(init) }
return FloatBuffer(FloatArray(size) { init(it) })
}
public inline fun FloatBuffer(size: Int, init: (Int) -> Float): FloatBuffer = FloatBuffer(FloatArray(size) { init(it) })
/**
* Returns a new [FloatBuffer] of given elements.
*/
fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats)
public fun FloatBuffer(vararg floats: Float): FloatBuffer = FloatBuffer(floats)
/**
* Returns a [FloatArray] containing all of the elements of this [MutableBuffer].
*/
val MutableBuffer<out Float>.array: FloatArray
public val MutableBuffer<out Float>.array: FloatArray
get() = (if (this is FloatBuffer) array else FloatArray(size) { get(it) })
/**
@ -52,4 +49,4 @@ val MutableBuffer<out Float>.array: FloatArray
* @receiver the array.
* @return the new buffer.
*/
fun FloatArray.asBuffer(): FloatBuffer = FloatBuffer(this)
public fun FloatArray.asBuffer(): FloatBuffer = FloatBuffer(this)

@ -1,15 +1,11 @@
package scientifik.kmath.structures
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
/**
* Specialized [MutableBuffer] implementation over [IntArray].
*
* @property array the underlying array.
*/
inline class IntBuffer(val array: IntArray) : MutableBuffer<Int> {
public inline class IntBuffer(public val array: IntArray) : MutableBuffer<Int> {
override val size: Int get() = array.size
override operator fun get(index: Int): Int = array[index]
@ -31,20 +27,17 @@ inline class IntBuffer(val array: IntArray) : MutableBuffer<Int> {
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an buffer element given its index.
*/
inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer {
contract { callsInPlace(init) }
return IntBuffer(IntArray(size) { init(it) })
}
public inline fun IntBuffer(size: Int, init: (Int) -> Int): IntBuffer = IntBuffer(IntArray(size) { init(it) })
/**
* Returns a new [IntBuffer] of given elements.
*/
fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints)
public fun IntBuffer(vararg ints: Int): IntBuffer = IntBuffer(ints)
/**
* Returns a [IntArray] containing all of the elements of this [MutableBuffer].
*/
val MutableBuffer<out Int>.array: IntArray
public val MutableBuffer<out Int>.array: IntArray
get() = (if (this is IntBuffer) array else IntArray(size) { get(it) })
/**
@ -53,4 +46,4 @@ val MutableBuffer<out Int>.array: IntArray
* @receiver the array.
* @return the new buffer.
*/
fun IntArray.asBuffer(): IntBuffer = IntBuffer(this)
public fun IntArray.asBuffer(): IntBuffer = IntBuffer(this)

@ -8,7 +8,7 @@ import kotlin.contracts.contract
*
* @property array the underlying array.
*/
inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
public inline class LongBuffer(public val array: LongArray) : MutableBuffer<Long> {
override val size: Int get() = array.size
override operator fun get(index: Int): Long = array[index]
@ -21,7 +21,6 @@ inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
override fun copy(): MutableBuffer<Long> =
LongBuffer(array.copyOf())
}
/**
@ -31,20 +30,17 @@ inline class LongBuffer(val array: LongArray) : MutableBuffer<Long> {
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an buffer element given its index.
*/
inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer {
contract { callsInPlace(init) }
return LongBuffer(LongArray(size) { init(it) })
}
public inline fun LongBuffer(size: Int, init: (Int) -> Long): LongBuffer = LongBuffer(LongArray(size) { init(it) })
/**
* Returns a new [LongBuffer] of given elements.
*/
fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs)
public fun LongBuffer(vararg longs: Long): LongBuffer = LongBuffer(longs)
/**
* Returns a [IntArray] containing all of the elements of this [MutableBuffer].
*/
val MutableBuffer<out Long>.array: LongArray
public val MutableBuffer<out Long>.array: LongArray
get() = (if (this is LongBuffer) array else LongArray(size) { get(it) })
/**
@ -53,4 +49,4 @@ val MutableBuffer<out Long>.array: LongArray
* @receiver the array.
* @return the new buffer.
*/
fun LongArray.asBuffer(): LongBuffer = LongBuffer(this)
public fun LongArray.asBuffer(): LongBuffer = LongBuffer(this)

@ -9,7 +9,7 @@ import scientifik.memory.*
* @property memory the underlying memory segment.
* @property spec the spec of [T] type.
*/
open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spec: MemorySpec<T>) : Buffer<T> {
public open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spec: MemorySpec<T>) : Buffer<T> {
override val size: Int get() = memory.size / spec.objectSize
private val reader: MemoryReader = memory.reader()
@ -17,20 +17,17 @@ open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spe
override operator fun get(index: Int): T = reader.read(spec, spec.objectSize * index)
override operator fun iterator(): Iterator<T> = (0 until size).asSequence().map { get(it) }.iterator()
companion object {
fun <T : Any> create(spec: MemorySpec<T>, size: Int): MemoryBuffer<T> =
public companion object {
public fun <T : Any> create(spec: MemorySpec<T>, size: Int): MemoryBuffer<T> =
MemoryBuffer(Memory.allocate(size * spec.objectSize), spec)
inline fun <T : Any> create(
public inline fun <T : Any> create(
spec: MemorySpec<T>,
size: Int,
crossinline initializer: (Int) -> T
): MemoryBuffer<T> =
MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer ->
(0 until size).forEach {
buffer[it] = initializer(it)
}
}
initializer: (Int) -> T
): MemoryBuffer<T> = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer ->
(0 until size).forEach { buffer[it] = initializer(it) }
}
}
}
@ -41,7 +38,7 @@ open class MemoryBuffer<T : Any>(protected val memory: Memory, protected val spe
* @property memory the underlying memory segment.
* @property spec the spec of [T] type.
*/
class MutableMemoryBuffer<T : Any>(memory: Memory, spec: MemorySpec<T>) : MemoryBuffer<T>(memory, spec),
public class MutableMemoryBuffer<T : Any>(memory: Memory, spec: MemorySpec<T>) : MemoryBuffer<T>(memory, spec),
MutableBuffer<T> {
private val writer: MemoryWriter = memory.writer()
@ -49,19 +46,16 @@ class MutableMemoryBuffer<T : Any>(memory: Memory, spec: MemorySpec<T>) : Memory
override operator fun set(index: Int, value: T): Unit = writer.write(spec, spec.objectSize * index, value)
override fun copy(): MutableBuffer<T> = MutableMemoryBuffer(memory.copy(), spec)
companion object {
fun <T : Any> create(spec: MemorySpec<T>, size: Int): MutableMemoryBuffer<T> =
public companion object {
public fun <T : Any> create(spec: MemorySpec<T>, size: Int): MutableMemoryBuffer<T> =
MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec)
inline fun <T : Any> create(
public inline fun <T : Any> create(
spec: MemorySpec<T>,
size: Int,
crossinline initializer: (Int) -> T
): MutableMemoryBuffer<T> =
MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer ->
(0 until size).forEach {
buffer[it] = initializer(it)
}
}
): MutableMemoryBuffer<T> = MutableMemoryBuffer(Memory.allocate(size * spec.objectSize), spec).also { buffer ->
(0 until size).forEach { buffer[it] = initializer(it) }
}
}
}

@ -5,12 +5,10 @@ import scientifik.kmath.operations.Field
import scientifik.kmath.operations.Ring
import scientifik.kmath.operations.Space
/**
* An exception is thrown when the expected ans actual shape of NDArray differs
*/
class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : RuntimeException()
public class ShapeMismatchException(public val expected: IntArray, public val actual: IntArray) : RuntimeException()
/**
* The base interface for all nd-algebra implementations
@ -18,53 +16,49 @@ class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : Run
* @param C the type of the element context
* @param N the type of the structure
*/
interface NDAlgebra<T, C, N : NDStructure<T>> {
val shape: IntArray
val elementContext: C
public interface NDAlgebra<T, C, N : NDStructure<T>> {
public val shape: IntArray
public val elementContext: C
/**
* Produce a new [N] structure using given initializer function
*/
fun produce(initializer: C.(IntArray) -> T): N
public fun produce(initializer: C.(IntArray) -> T): N
/**
* Map elements from one structure to another one
*/
fun map(arg: N, transform: C.(T) -> T): N
public fun map(arg: N, transform: C.(T) -> T): N
/**
* Map indexed elements
*/
fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N
public fun mapIndexed(arg: N, transform: C.(index: IntArray, T) -> T): N
/**
* Combine two structures into one
*/
fun combine(a: N, b: N, transform: C.(T, T) -> T): N
public fun combine(a: N, b: N, transform: C.(T, T) -> T): N
/**
* Check if given elements are consistent with this context
*/
fun check(vararg elements: N) {
elements.forEach {
if (!shape.contentEquals(it.shape)) {
throw ShapeMismatchException(shape, it.shape)
}
}
public fun check(vararg elements: N): Unit = elements.forEach {
if (!shape.contentEquals(it.shape)) throw ShapeMismatchException(shape, it.shape)
}
/**
* element-by-element invoke a function working on [T] on a [NDStructure]
*/
operator fun Function1<T, T>.invoke(structure: N): N = map(structure) { value -> this@invoke(value) }
public operator fun Function1<T, T>.invoke(structure: N): N = map(structure) { value -> this@invoke(value) }
companion object
public companion object
}
/**
* An nd-space over element space
*/
interface NDSpace<T, S : Space<T>, N : NDStructure<T>> : Space<N>, NDAlgebra<T, S, N> {
public interface NDSpace<T, S : Space<T>, N : NDStructure<T>> : Space<N>, NDAlgebra<T, S, N> {
/**
* Element-by-element addition
*/
@ -76,32 +70,31 @@ interface NDSpace<T, S : Space<T>, N : NDStructure<T>> : Space<N>, NDAlgebra<T,
override fun multiply(a: N, k: Number): N = map(a) { multiply(it, k) }
//TODO move to extensions after KEEP-176
operator fun N.plus(arg: T): N = map(this) { value -> add(arg, value) }
public operator fun N.plus(arg: T): N = map(this) { value -> add(arg, value) }
operator fun N.minus(arg: T): N = map(this) { value -> add(arg, -value) }
public operator fun N.minus(arg: T): N = map(this) { value -> add(arg, -value) }
operator fun T.plus(arg: N): N = map(arg) { value -> add(this@plus, value) }
operator fun T.minus(arg: N): N = map(arg) { value -> add(-this@minus, value) }
public operator fun T.plus(arg: N): N = map(arg) { value -> add(this@plus, value) }
public operator fun T.minus(arg: N): N = map(arg) { value -> add(-this@minus, value) }
companion object
public companion object
}
/**
* An nd-ring over element ring
*/
interface NDRing<T, R : Ring<T>, N : NDStructure<T>> : Ring<N>, NDSpace<T, R, N> {
public interface NDRing<T, R : Ring<T>, N : NDStructure<T>> : Ring<N>, NDSpace<T, R, N> {
/**
* Element-by-element multiplication
*/
override fun multiply(a: N, b: N): N = combine(a, b) { aValue, bValue -> multiply(aValue, bValue) }
//TODO move to extensions after KEEP-176
operator fun N.times(arg: T): N = map(this) { value -> multiply(arg, value) }
public operator fun N.times(arg: T): N = map(this) { value -> multiply(arg, value) }
operator fun T.times(arg: N): N = map(arg) { value -> multiply(this@times, value) }
public operator fun T.times(arg: N): N = map(arg) { value -> multiply(this@times, value) }
companion object
public companion object
}
/**
@ -111,31 +104,29 @@ interface NDRing<T, R : Ring<T>, N : NDStructure<T>> : Ring<N>, NDSpace<T, R, N>
* @param N the type of ND structure.
* @param F field of structure elements.
*/
interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F, N> {
public interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F, N> {
/**
* Element-by-element division
*/
override fun divide(a: N, b: N): N = combine(a, b) { aValue, bValue -> divide(aValue, bValue) }
//TODO move to extensions after KEEP-176
operator fun N.div(arg: T): N = map(this) { value -> divide(arg, value) }
public operator fun N.div(arg: T): N = map(this) { value -> divide(arg, value) }
operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) }
public operator fun T.div(arg: N): N = map(arg) { divide(it, this@div) }
companion object {
private val realNDFieldCache = HashMap<IntArray, RealNDField>()
public companion object {
private val realNDFieldCache: MutableMap<IntArray, RealNDField> = hashMapOf()
/**
* Create a nd-field for [Double] values or pull it from cache if it was created previously
*/
fun real(vararg shape: Int): RealNDField = realNDFieldCache.getOrPut(shape) { RealNDField(shape) }
public fun real(vararg shape: Int): RealNDField = realNDFieldCache.getOrPut(shape) { RealNDField(shape) }
/**
* Create a nd-field with boxing generic buffer
*/
fun <T : Any, F : Field<T>> boxing(
public fun <T : Any, F : Field<T>> boxing(
field: F,
vararg shape: Int,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
@ -145,7 +136,7 @@ interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F,
* Create a most suitable implementation for nd-field using reified class.
*/
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any, F : Field<T>> auto(field: F, vararg shape: Int): BufferedNDField<T, F> =
public inline fun <reified T : Any, F : Field<T>> auto(field: F, vararg shape: Int): BufferedNDField<T, F> =
when {
T::class == Double::class -> real(*shape) as BufferedNDField<T, F>
T::class == Complex::class -> complex(*shape) as BufferedNDField<T, F>

@ -4,6 +4,7 @@ import scientifik.kmath.operations.Field
import scientifik.kmath.operations.RealField
import scientifik.kmath.operations.Ring
import scientifik.kmath.operations.Space
import kotlin.contracts.contract
/**
* The root for all [NDStructure] based algebra elements. Does not implement algebra element root because of problems with recursive self-types
@ -11,31 +12,30 @@ import scientifik.kmath.operations.Space
* @param C the type of the context for the element
* @param N the type of the underlying [NDStructure]
*/
interface NDElement<T, C, N : NDStructure<T>> : NDStructure<T> {
public interface NDElement<T, C, N : NDStructure<T>> : NDStructure<T> {
public val context: NDAlgebra<T, C, N>
val context: NDAlgebra<T, C, N>
public fun unwrap(): N
fun unwrap(): N
public fun N.wrap(): NDElement<T, C, N>
fun N.wrap(): NDElement<T, C, N>
companion object {
public companion object {
/**
* Create a optimized NDArray of doubles
*/
fun real(shape: IntArray, initializer: RealField.(IntArray) -> Double = { 0.0 }): RealNDElement =
public fun real(shape: IntArray, initializer: RealField.(IntArray) -> Double = { 0.0 }): RealNDElement =
NDField.real(*shape).produce(initializer)
inline fun real1D(dim: Int, crossinline initializer: (Int) -> Double = { _ -> 0.0 }): RealNDElement =
public inline fun real1D(dim: Int, crossinline initializer: (Int) -> Double = { _ -> 0.0 }): RealNDElement =
real(intArrayOf(dim)) { initializer(it[0]) }
inline fun real2D(
public inline fun real2D(
dim1: Int,
dim2: Int,
crossinline initializer: (Int, Int) -> Double = { _, _ -> 0.0 }
): RealNDElement = real(intArrayOf(dim1, dim2)) { initializer(it[0], it[1]) }
inline fun real3D(
public inline fun real3D(
dim1: Int,
dim2: Int,
dim3: Int,
@ -46,7 +46,7 @@ interface NDElement<T, C, N : NDStructure<T>> : NDStructure<T> {
/**
* Simple boxing NDArray
*/
fun <T : Any, F : Field<T>> boxing(
public fun <T : Any, F : Field<T>> boxing(
shape: IntArray,
field: F,
initializer: F.(IntArray) -> T
@ -55,7 +55,7 @@ interface NDElement<T, C, N : NDStructure<T>> : NDStructure<T> {
return ndField.produce(initializer)
}
inline fun <reified T : Any, F : Field<T>> auto(
public inline fun <reified T : Any, F : Field<T>> auto(
shape: IntArray,
field: F,
noinline initializer: F.(IntArray) -> T
@ -66,17 +66,16 @@ interface NDElement<T, C, N : NDStructure<T>> : NDStructure<T> {
}
}
fun <T, C, N : NDStructure<T>> NDElement<T, C, N>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDElement<T, C, N> =
public fun <T, C, N : NDStructure<T>> NDElement<T, C, N>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDElement<T, C, N> =
context.mapIndexed(unwrap(), transform).wrap()
fun <T, C, N : NDStructure<T>> NDElement<T, C, N>.map(transform: C.(T) -> T): NDElement<T, C, N> =
public fun <T, C, N : NDStructure<T>> NDElement<T, C, N>.map(transform: C.(T) -> T): NDElement<T, C, N> =
context.map(unwrap(), transform).wrap()
/**
* Element by element application of any operation on elements to the whole [NDElement]
*/
operator fun <T, C, N : NDStructure<T>> Function1<T, T>.invoke(ndElement: NDElement<T, C, N>): NDElement<T, C, N> =
public operator fun <T, C, N : NDStructure<T>> Function1<T, T>.invoke(ndElement: NDElement<T, C, N>): NDElement<T, C, N> =
ndElement.map { value -> this@invoke(value) }
/* plus and minus */
@ -84,13 +83,13 @@ operator fun <T, C, N : NDStructure<T>> Function1<T, T>.invoke(ndElement: NDElem
/**
* Summation operation for [NDElement] and single element
*/
operator fun <T, S : Space<T>, N : NDStructure<T>> NDElement<T, S, N>.plus(arg: T): NDElement<T, S, N> =
public operator fun <T, S : Space<T>, N : NDStructure<T>> NDElement<T, S, N>.plus(arg: T): NDElement<T, S, N> =
map { value -> arg + value }
/**
* Subtraction operation between [NDElement] and single element
*/
operator fun <T, S : Space<T>, N : NDStructure<T>> NDElement<T, S, N>.minus(arg: T): NDElement<T, S, N> =
public operator fun <T, S : Space<T>, N : NDStructure<T>> NDElement<T, S, N>.minus(arg: T): NDElement<T, S, N> =
map { value -> arg - value }
/* prod and div */
@ -98,13 +97,13 @@ operator fun <T, S : Space<T>, N : NDStructure<T>> NDElement<T, S, N>.minus(arg:
/**
* Product operation for [NDElement] and single element
*/
operator fun <T, R : Ring<T>, N : NDStructure<T>> NDElement<T, R, N>.times(arg: T): NDElement<T, R, N> =
public operator fun <T, R : Ring<T>, N : NDStructure<T>> NDElement<T, R, N>.times(arg: T): NDElement<T, R, N> =
map { value -> arg * value }
/**
* Division operation between [NDElement] and single element
*/
operator fun <T, F : Field<T>, N : NDStructure<T>> NDElement<T, F, N>.div(arg: T): NDElement<T, F, N> =
public operator fun <T, F : Field<T>, N : NDStructure<T>> NDElement<T, F, N>.div(arg: T): NDElement<T, F, N> =
map { value -> arg / value }
// /**

@ -1,6 +1,5 @@
package scientifik.kmath.structures
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.jvm.JvmName
import kotlin.reflect.KClass
@ -12,17 +11,17 @@ import kotlin.reflect.KClass
*
* @param T the type of items.
*/
interface NDStructure<T> {
public interface NDStructure<T> {
/**
* The shape of structure, i.e. non-empty sequence of non-negative integers that specify sizes of dimensions of
* this structure.
*/
val shape: IntArray
public val shape: IntArray
/**
* The count of dimensions in this structure. It should be equal to size of [shape].
*/
val dimension: Int get() = shape.size
public val dimension: Int get() = shape.size
/**
* Returns the value at the specified indices.
@ -30,24 +29,24 @@ interface NDStructure<T> {
* @param index the indices.
* @return the value.
*/
operator fun get(index: IntArray): T
public operator fun get(index: IntArray): T
/**
* Returns the sequence of all the elements associated by their indices.
*
* @return the lazy sequence of pairs of indices to values.
*/
fun elements(): Sequence<Pair<IntArray, T>>
public fun elements(): Sequence<Pair<IntArray, T>>
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
companion object {
public companion object {
/**
* Indicates whether some [NDStructure] is equal to another one.
*/
fun equals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean {
public fun equals(st1: NDStructure<*>, st2: NDStructure<*>): Boolean {
if (st1 === st2) return true
// fast comparison of buffers if possible
@ -68,7 +67,7 @@ interface NDStructure<T> {
*
* Strides should be reused if possible.
*/
fun <T> build(
public fun <T> build(
strides: Strides,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
initializer: (IntArray) -> T
@ -78,39 +77,39 @@ interface NDStructure<T> {
/**
* Inline create NDStructure with non-boxing buffer implementation if it is possible
*/
inline fun <reified T : Any> auto(
public inline fun <reified T : Any> auto(
strides: Strides,
crossinline initializer: (IntArray) -> T
): BufferNDStructure<T> =
BufferNDStructure(strides, Buffer.auto(strides.linearSize) { i -> initializer(strides.index(i)) })
inline fun <T : Any> auto(
public inline fun <T : Any> auto(
type: KClass<T>,
strides: Strides,
crossinline initializer: (IntArray) -> T
): BufferNDStructure<T> =
BufferNDStructure(strides, Buffer.auto(type, strides.linearSize) { i -> initializer(strides.index(i)) })
fun <T> build(
public fun <T> build(
shape: IntArray,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
initializer: (IntArray) -> T
): BufferNDStructure<T> = build(DefaultStrides(shape), bufferFactory, initializer)
inline fun <reified T : Any> auto(
public inline fun <reified T : Any> auto(
shape: IntArray,
crossinline initializer: (IntArray) -> T
): BufferNDStructure<T> =
auto(DefaultStrides(shape), initializer)
@JvmName("autoVarArg")
inline fun <reified T : Any> auto(
public inline fun <reified T : Any> auto(
vararg shape: Int,
crossinline initializer: (IntArray) -> T
): BufferNDStructure<T> =
auto(DefaultStrides(shape), initializer)
inline fun <T : Any> auto(
public inline fun <T : Any> auto(
type: KClass<T>,
vararg shape: Int,
crossinline initializer: (IntArray) -> T
@ -125,68 +124,68 @@ interface NDStructure<T> {
* @param index the indices.
* @return the value.
*/
operator fun <T> NDStructure<T>.get(vararg index: Int): T = get(index)
public operator fun <T> NDStructure<T>.get(vararg index: Int): T = get(index)
/**
* Represents mutable [NDStructure].
*/
interface MutableNDStructure<T> : NDStructure<T> {
public interface MutableNDStructure<T> : NDStructure<T> {
/**
* Inserts an item at the specified indices.
*
* @param index the indices.
* @param value the value.
*/
operator fun set(index: IntArray, value: T)
public operator fun set(index: IntArray, value: T)
}
inline fun <T> MutableNDStructure<T>.mapInPlace(action: (IntArray, T) -> T) {
contract { callsInPlace(action) }
public inline fun <T> MutableNDStructure<T>.mapInPlace(action: (IntArray, T) -> T): Unit =
elements().forEach { (index, oldValue) -> this[index] = action(index, oldValue) }
}
/**
* A way to convert ND index to linear one and back.
*/
interface Strides {
public interface Strides {
/**
* Shape of NDstructure
*/
val shape: IntArray
public val shape: IntArray
/**
* Array strides
*/
val strides: List<Int>
public val strides: List<Int>
/**
* Get linear index from multidimensional index
*/
fun offset(index: IntArray): Int
public fun offset(index: IntArray): Int
/**
* Get multidimensional from linear
*/
fun index(offset: Int): IntArray
public fun index(offset: Int): IntArray
/**
* The size of linear buffer to accommodate all elements of ND-structure corresponding to strides
*/
val linearSize: Int
public val linearSize: Int
// TODO introduce a fast way to calculate index of the next element?
/**
* Iterate over ND indices in a natural order
*/
fun indices(): Sequence<IntArray> {
//TODO introduce a fast way to calculate index of the next element?
return (0 until linearSize).asSequence().map { index(it) }
}
public fun indices(): Sequence<IntArray> = (0 until linearSize).asSequence().map { index(it) }
}
/**
* Simple implementation of [Strides].
*/
class DefaultStrides private constructor(override val shape: IntArray) : Strides {
public class DefaultStrides private constructor(override val shape: IntArray) : Strides {
override val linearSize: Int
get() = strides[shape.size]
/**
* Strides for memory access
*/
@ -194,6 +193,7 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides
sequence {
var current = 1
yield(1)
shape.forEach {
current *= it
yield(current)
@ -212,17 +212,16 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides
val res = IntArray(shape.size)
var current = offset
var strideIndex = strides.size - 2
while (strideIndex >= 0) {
res[strideIndex] = (current / strides[strideIndex])
current %= strides[strideIndex]
strideIndex--
}
return res
}
override val linearSize: Int
get() = strides[shape.size]
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is DefaultStrides) return false
@ -232,13 +231,14 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides
override fun hashCode(): Int = shape.contentHashCode()
companion object {
public companion object {
private val defaultStridesCache = HashMap<IntArray, Strides>()
/**
* Cached builder for default strides
*/
operator fun invoke(shape: IntArray): Strides = defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) }
public operator fun invoke(shape: IntArray): Strides =
defaultStridesCache.getOrPut(shape) { DefaultStrides(shape) }
}
}
@ -247,16 +247,16 @@ class DefaultStrides private constructor(override val shape: IntArray) : Strides
*
* @param T the type of items.
*/
abstract class NDBuffer<T> : NDStructure<T> {
public abstract class NDBuffer<T> : NDStructure<T> {
/**
* The underlying buffer.
*/
abstract val buffer: Buffer<T>
public abstract val buffer: Buffer<T>
/**
* The strides to access elements of [Buffer] by linear indices.
*/
abstract val strides: Strides
public abstract val strides: Strides
override operator fun get(index: IntArray): T = buffer[strides.offset(index)]
@ -278,7 +278,7 @@ abstract class NDBuffer<T> : NDStructure<T> {
/**
* Boxing generic [NDStructure]
*/
class BufferNDStructure<T>(
public class BufferNDStructure<T>(
override val strides: Strides,
override val buffer: Buffer<T>
) : NDBuffer<T>() {
@ -292,13 +292,13 @@ class BufferNDStructure<T>(
/**
* Transform structure to a new structure using provided [BufferFactory] and optimizing if argument is [BufferNDStructure]
*/
inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer(
public inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer(
factory: BufferFactory<R> = Buffer.Companion::auto,
crossinline transform: (T) -> R
): BufferNDStructure<R> {
return if (this is BufferNDStructure<T>) {
return if (this is BufferNDStructure<T>)
BufferNDStructure(this.strides, factory.invoke(strides.linearSize) { transform(buffer[it]) })
} else {
else {
val strides = DefaultStrides(shape)
BufferNDStructure(strides, factory.invoke(strides.linearSize) { transform(get(strides.index(it))) })
}
@ -307,7 +307,7 @@ inline fun <T, reified R : Any> NDStructure<T>.mapToBuffer(
/**
* Mutable ND buffer based on linear [MutableBuffer].
*/
class MutableBufferNDStructure<T>(
public class MutableBufferNDStructure<T>(
override val strides: Strides,
override val buffer: MutableBuffer<T>
) : NDBuffer<T>(), MutableNDStructure<T> {
@ -321,7 +321,7 @@ class MutableBufferNDStructure<T>(
override operator fun set(index: IntArray, value: T): Unit = buffer.set(strides.offset(index), value)
}
inline fun <reified T : Any> NDStructure<T>.combine(
public inline fun <reified T : Any> NDStructure<T>.combine(
struct: NDStructure<T>,
crossinline block: (T, T) -> T
): NDStructure<T> {

@ -1,14 +1,11 @@
package scientifik.kmath.structures
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
/**
* Specialized [MutableBuffer] implementation over [DoubleArray].
*
* @property array the underlying array.
*/
inline class RealBuffer(val array: DoubleArray) : MutableBuffer<Double> {
public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer<Double> {
override val size: Int get() = array.size
override operator fun get(index: Int): Double = array[index]
@ -30,20 +27,17 @@ inline class RealBuffer(val array: DoubleArray) : MutableBuffer<Double> {
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an buffer element given its index.
*/
inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer {
contract { callsInPlace(init) }
return RealBuffer(DoubleArray(size) { init(it) })
}
public inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = RealBuffer(DoubleArray(size) { init(it) })
/**
* Returns a new [RealBuffer] of given elements.
*/
fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
/**
* Returns a [DoubleArray] containing all of the elements of this [MutableBuffer].
*/
val MutableBuffer<out Double>.array: DoubleArray
public val MutableBuffer<out Double>.array: DoubleArray
get() = (if (this is RealBuffer) array else DoubleArray(size) { get(it) })
/**
@ -52,4 +46,4 @@ val MutableBuffer<out Double>.array: DoubleArray
* @receiver the array.
* @return the new buffer.
*/
fun DoubleArray.asBuffer(): RealBuffer = RealBuffer(this)
public fun DoubleArray.asBuffer(): RealBuffer = RealBuffer(this)

@ -4,12 +4,11 @@ import scientifik.kmath.operations.ExtendedField
import scientifik.kmath.operations.ExtendedFieldOperations
import kotlin.math.*
/**
* [ExtendedFieldOperations] over [RealBuffer].
*/
object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
public object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(b.size == a.size) {
"The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
}
@ -21,7 +20,7 @@ object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
} else RealBuffer(DoubleArray(a.size) { a[it] + b[it] })
}
override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
val kValue = k.toDouble()
return if (a is RealBuffer) {
@ -30,7 +29,7 @@ object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
} else RealBuffer(DoubleArray(a.size) { a[it] * kValue })
}
override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(b.size == a.size) {
"The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
}
@ -43,7 +42,7 @@ object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
RealBuffer(DoubleArray(a.size) { a[it] * b[it] })
}
override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
public override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(b.size == a.size) {
"The size of the first buffer ${a.size} should be the same as for second one: ${b.size} "
}
@ -55,84 +54,91 @@ object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
} else RealBuffer(DoubleArray(a.size) { a[it] / b[it] })
}
override fun sin(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun sin(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { sin(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { sin(arg[it]) })
override fun cos(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun cos(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { cos(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { cos(arg[it]) })
override fun tan(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun tan(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { tan(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { tan(arg[it]) })
override fun asin(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun asin(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { asin(array[it]) })
} else {
} else
RealBuffer(DoubleArray(arg.size) { asin(arg[it]) })
}
override fun acos(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun acos(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { acos(array[it]) })
} else
RealBuffer(DoubleArray(arg.size) { acos(arg[it]) })
override fun atan(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun atan(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { atan(array[it]) })
} else
RealBuffer(DoubleArray(arg.size) { atan(arg[it]) })
override fun sinh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun sinh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { sinh(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { sinh(arg[it]) })
override fun cosh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun cosh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { cosh(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { cosh(arg[it]) })
override fun tanh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun tanh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { tanh(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { tanh(arg[it]) })
override fun asinh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun asinh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { asinh(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { asinh(arg[it]) })
override fun acosh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun acosh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { acosh(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { acosh(arg[it]) })
override fun atanh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun atanh(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { atanh(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { atanh(arg[it]) })
override fun power(arg: Buffer<Double>, pow: Number): RealBuffer = if (arg is RealBuffer) {
public override fun power(arg: Buffer<Double>, pow: Number): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { array[it].pow(pow.toDouble()) })
} else RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) })
} else
RealBuffer(DoubleArray(arg.size) { arg[it].pow(pow.toDouble()) })
override fun exp(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun exp(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { exp(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { exp(arg[it]) })
override fun ln(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
public override fun ln(arg: Buffer<Double>): RealBuffer = if (arg is RealBuffer) {
val array = arg.array
RealBuffer(DoubleArray(arg.size) { ln(array[it]) })
} else RealBuffer(DoubleArray(arg.size) { ln(arg[it]) })
} else
RealBuffer(DoubleArray(arg.size) { ln(arg[it]) })
}
/**
@ -140,101 +146,101 @@ object RealBufferFieldOperations : ExtendedFieldOperations<Buffer<Double>> {
*
* @property size the size of buffers to operate on.
*/
class RealBufferField(val size: Int) : ExtendedField<Buffer<Double>> {
override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
public class RealBufferField(public val size: Int) : ExtendedField<Buffer<Double>> {
public override val zero: Buffer<Double> by lazy { RealBuffer(size) { 0.0 } }
public override val one: Buffer<Double> by lazy { RealBuffer(size) { 1.0 } }
override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
public override fun add(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
return RealBufferFieldOperations.add(a, b)
}
override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
public override fun multiply(a: Buffer<Double>, k: Number): RealBuffer {
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
return RealBufferFieldOperations.multiply(a, k)
}
override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
public override fun multiply(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
return RealBufferFieldOperations.multiply(a, b)
}
override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
public override fun divide(a: Buffer<Double>, b: Buffer<Double>): RealBuffer {
require(a.size == size) { "The buffer size ${a.size} does not match context size $size" }
return RealBufferFieldOperations.divide(a, b)
}
override fun sin(arg: Buffer<Double>): RealBuffer {
public override fun sin(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.sin(arg)
}
override fun cos(arg: Buffer<Double>): RealBuffer {
public override fun cos(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.cos(arg)
}
override fun tan(arg: Buffer<Double>): RealBuffer {
public override fun tan(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.tan(arg)
}
override fun asin(arg: Buffer<Double>): RealBuffer {
public override fun asin(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.asin(arg)
}
override fun acos(arg: Buffer<Double>): RealBuffer {
public override fun acos(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.acos(arg)
}
override fun atan(arg: Buffer<Double>): RealBuffer {
public override fun atan(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.atan(arg)
}
override fun sinh(arg: Buffer<Double>): RealBuffer {
public override fun sinh(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.sinh(arg)
}
override fun cosh(arg: Buffer<Double>): RealBuffer {
public override fun cosh(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.cosh(arg)
}
override fun tanh(arg: Buffer<Double>): RealBuffer {
public override fun tanh(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.tanh(arg)
}
override fun asinh(arg: Buffer<Double>): RealBuffer {
public override fun asinh(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.asinh(arg)
}
override fun acosh(arg: Buffer<Double>): RealBuffer {
public override fun acosh(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.acosh(arg)
}
override fun atanh(arg: Buffer<Double>): RealBuffer {
public override fun atanh(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.atanh(arg)
}
override fun power(arg: Buffer<Double>, pow: Number): RealBuffer {
public override fun power(arg: Buffer<Double>, pow: Number): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.power(arg, pow)
}
override fun exp(arg: Buffer<Double>): RealBuffer {
public override fun exp(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.exp(arg)
}
override fun ln(arg: Buffer<Double>): RealBuffer {
public override fun ln(arg: Buffer<Double>): RealBuffer {
require(arg.size == size) { "The buffer size ${arg.size} does not match context size $size" }
return RealBufferFieldOperations.ln(arg)
}

@ -3,9 +3,9 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.FieldElement
import scientifik.kmath.operations.RealField
typealias RealNDElement = BufferedNDFieldElement<Double, RealField>
public typealias RealNDElement = BufferedNDFieldElement<Double, RealField>
class RealNDField(override val shape: IntArray) :
public class RealNDField(override val shape: IntArray) :
BufferedNDField<Double, RealField>,
ExtendedNDField<Double, RealField, NDBuffer<Double>> {
@ -15,7 +15,7 @@ class RealNDField(override val shape: IntArray) :
override val zero: RealNDElement by lazy { produce { zero } }
override val one: RealNDElement by lazy { produce { one } }
inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Double): Buffer<Double> =
RealBuffer(DoubleArray(size) { initializer(it) })
/**
@ -90,7 +90,7 @@ class RealNDField(override val shape: IntArray) :
/**
* Fast element production using function inlining
*/
inline fun BufferedNDField<Double, RealField>.produceInline(crossinline initializer: RealField.(Int) -> Double): RealNDElement {
public inline fun BufferedNDField<Double, RealField>.produceInline(crossinline initializer: RealField.(Int) -> Double): RealNDElement {
val array = DoubleArray(strides.linearSize) { offset -> RealField.initializer(offset) }
return BufferedNDFieldElement(this, RealBuffer(array))
}
@ -98,13 +98,13 @@ inline fun BufferedNDField<Double, RealField>.produceInline(crossinline initiali
/**
* Map one [RealNDElement] using function with indices.
*/
inline fun RealNDElement.mapIndexed(crossinline transform: RealField.(index: IntArray, Double) -> Double): RealNDElement =
public inline fun RealNDElement.mapIndexed(crossinline transform: RealField.(index: IntArray, Double) -> Double): RealNDElement =
context.produceInline { offset -> transform(strides.index(offset), buffer[offset]) }
/**
* Map one [RealNDElement] using function without indices.
*/
inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double): RealNDElement {
public inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double): RealNDElement {
val array = DoubleArray(strides.linearSize) { offset -> RealField.transform(buffer[offset]) }
return BufferedNDFieldElement(context, RealBuffer(array))
}
@ -112,26 +112,22 @@ inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double
/**
* Element by element application of any operation on elements to the whole array. Just like in numpy.
*/
operator fun Function1<Double, Double>.invoke(ndElement: RealNDElement): RealNDElement =
public operator fun Function1<Double, Double>.invoke(ndElement: RealNDElement): RealNDElement =
ndElement.map { this@invoke(it) }
/* plus and minus */
/**
* Summation operation for [BufferedNDElement] and single element
*/
operator fun RealNDElement.plus(arg: Double): RealNDElement =
map { it + arg }
public operator fun RealNDElement.plus(arg: Double): RealNDElement = map { it + arg }
/**
* Subtraction operation between [BufferedNDElement] and single element
*/
operator fun RealNDElement.minus(arg: Double): RealNDElement =
map { it - arg }
public operator fun RealNDElement.minus(arg: Double): RealNDElement = map { it - arg }
/**
* Produce a context for n-dimensional operations inside this real field
*/
inline fun <R> RealField.nd(vararg shape: Int, action: RealNDField.() -> R): R = NDField.real(*shape).run(action)
public inline fun <R> RealField.nd(vararg shape: Int, action: RealNDField.() -> R): R = NDField.real(*shape).run(action)

@ -1,26 +1,21 @@
package scientifik.kmath.structures
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
/**
* Specialized [MutableBuffer] implementation over [ShortArray].
*
* @property array the underlying array.
*/
inline class ShortBuffer(val array: ShortArray) : MutableBuffer<Short> {
override val size: Int get() = array.size
public inline class ShortBuffer(public val array: ShortArray) : MutableBuffer<Short> {
public override val size: Int get() = array.size
override operator fun get(index: Int): Short = array[index]
public override operator fun get(index: Int): Short = array[index]
override operator fun set(index: Int, value: Short) {
public override operator fun set(index: Int, value: Short) {
array[index] = value
}
override operator fun iterator(): ShortIterator = array.iterator()
override fun copy(): MutableBuffer<Short> =
ShortBuffer(array.copyOf())
public override operator fun iterator(): ShortIterator = array.iterator()
public override fun copy(): MutableBuffer<Short> = ShortBuffer(array.copyOf())
}
/**
@ -30,20 +25,17 @@ inline class ShortBuffer(val array: ShortArray) : MutableBuffer<Short> {
* The function [init] is called for each array element sequentially starting from the first one.
* It should return the value for an buffer element given its index.
*/
inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer {
contract { callsInPlace(init) }
return ShortBuffer(ShortArray(size) { init(it) })
}
public inline fun ShortBuffer(size: Int, init: (Int) -> Short): ShortBuffer = ShortBuffer(ShortArray(size) { init(it) })
/**
* Returns a new [ShortBuffer] of given elements.
*/
fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts)
public fun ShortBuffer(vararg shorts: Short): ShortBuffer = ShortBuffer(shorts)
/**
* Returns a [ShortArray] containing all of the elements of this [MutableBuffer].
*/
val MutableBuffer<out Short>.array: ShortArray
public val MutableBuffer<out Short>.array: ShortArray
get() = (if (this is ShortBuffer) array else ShortArray(size) { get(it) })
/**
@ -52,4 +44,4 @@ val MutableBuffer<out Short>.array: ShortArray
* @receiver the array.
* @return the new buffer.
*/
fun ShortArray.asBuffer(): ShortBuffer = ShortBuffer(this)
public fun ShortArray.asBuffer(): ShortBuffer = ShortBuffer(this)

@ -3,19 +3,17 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.RingElement
import scientifik.kmath.operations.ShortRing
public typealias ShortNDElement = BufferedNDRingElement<Short, ShortRing>
typealias ShortNDElement = BufferedNDRingElement<Short, ShortRing>
class ShortNDRing(override val shape: IntArray) :
public class ShortNDRing(override val shape: IntArray) :
BufferedNDRing<Short, ShortRing> {
override val strides: Strides = DefaultStrides(shape)
override val elementContext: ShortRing get() = ShortRing
override val zero: ShortNDElement by lazy { produce { zero } }
override val one: ShortNDElement by lazy { produce { one } }
inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Short): Buffer<Short> =
public inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Short): Buffer<Short> =
ShortBuffer(ShortArray(size) { initializer(it) })
/**
@ -70,15 +68,13 @@ class ShortNDRing(override val shape: IntArray) :
/**
* Fast element production using function inlining.
*/
inline fun BufferedNDRing<Short, ShortRing>.produceInline(crossinline initializer: ShortRing.(Int) -> Short): ShortNDElement {
val array = ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) }
return BufferedNDRingElement(this, ShortBuffer(array))
}
public inline fun BufferedNDRing<Short, ShortRing>.produceInline(crossinline initializer: ShortRing.(Int) -> Short): ShortNDElement =
BufferedNDRingElement(this, ShortBuffer(ShortArray(strides.linearSize) { offset -> ShortRing.initializer(offset) }))
/**
* Element by element application of any operation on elements to the whole array.
*/
operator fun Function1<Short, Short>.invoke(ndElement: ShortNDElement): ShortNDElement =
public operator fun Function1<Short, Short>.invoke(ndElement: ShortNDElement): ShortNDElement =
ndElement.context.produceInline { i -> invoke(ndElement.buffer[i]) }
@ -87,11 +83,11 @@ operator fun Function1<Short, Short>.invoke(ndElement: ShortNDElement): ShortNDE
/**
* Summation operation for [ShortNDElement] and single element.
*/
operator fun ShortNDElement.plus(arg: Short): ShortNDElement =
public operator fun ShortNDElement.plus(arg: Short): ShortNDElement =
context.produceInline { i -> (buffer[i] + arg).toShort() }
/**
* Subtraction operation between [ShortNDElement] and single element.
*/
operator fun ShortNDElement.minus(arg: Short): ShortNDElement =
public operator fun ShortNDElement.minus(arg: Short): ShortNDElement =
context.produceInline { i -> (buffer[i] - arg).toShort() }

@ -3,27 +3,25 @@ package scientifik.kmath.structures
/**
* A structure that is guaranteed to be one-dimensional
*/
interface Structure1D<T> : NDStructure<T>, Buffer<T> {
override val dimension: Int get() = 1
public interface Structure1D<T> : NDStructure<T>, Buffer<T> {
public override val dimension: Int get() = 1
override operator fun get(index: IntArray): T {
public override operator fun get(index: IntArray): T {
require(index.size == 1) { "Index dimension mismatch. Expected 1 but found ${index.size}" }
return get(index[0])
}
override operator fun iterator(): Iterator<T> = (0 until size).asSequence().map { get(it) }.iterator()
public override operator fun iterator(): Iterator<T> = (0 until size).asSequence().map(::get).iterator()
}
/**
* A 1D wrapper for nd-structure
*/
private inline class Structure1DWrapper<T>(val structure: NDStructure<T>) : Structure1D<T> {
private inline class Structure1DWrapper<T>(public val structure: NDStructure<T>) : Structure1D<T> {
override val shape: IntArray get() = structure.shape
override val size: Int get() = structure.shape[0]
override operator fun get(index: Int): T = structure[index]
override fun elements(): Sequence<Pair<IntArray, T>> = structure.elements()
}
@ -33,7 +31,6 @@ private inline class Structure1DWrapper<T>(val structure: NDStructure<T>) : Stru
*/
private inline class Buffer1DWrapper<T>(val buffer: Buffer<T>) : Structure1D<T> {
override val shape: IntArray get() = intArrayOf(buffer.size)
override val size: Int get() = buffer.size
override fun elements(): Sequence<Pair<IntArray, T>> =
@ -45,18 +42,12 @@ private inline class Buffer1DWrapper<T>(val buffer: Buffer<T>) : Structure1D<T>
/**
* Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch
*/
fun <T> NDStructure<T>.as1D(): Structure1D<T> = if (shape.size == 1) {
if (this is NDBuffer) {
Buffer1DWrapper(this.buffer)
} else {
Structure1DWrapper(this)
}
} else {
public fun <T> NDStructure<T>.as1D(): Structure1D<T> = if (shape.size == 1) {
if (this is NDBuffer) Buffer1DWrapper(this.buffer) else Structure1DWrapper(this)
} else
error("Can't create 1d-structure from ${shape.size}d-structure")
}
/**
* Represent this buffer as 1D structure
*/
fun <T> Buffer<T>.asND(): Structure1D<T> = Buffer1DWrapper(this)
public fun <T> Buffer<T>.asND(): Structure1D<T> = Buffer1DWrapper(this)

@ -3,36 +3,29 @@ package scientifik.kmath.structures
/**
* A structure that is guaranteed to be two-dimensional
*/
interface Structure2D<T> : NDStructure<T> {
val rowNum: Int get() = shape[0]
val colNum: Int get() = shape[1]
public interface Structure2D<T> : NDStructure<T> {
public val rowNum: Int get() = shape[0]
public val colNum: Int get() = shape[1]
operator fun get(i: Int, j: Int): T
public operator fun get(i: Int, j: Int): T
override operator fun get(index: IntArray): T {
require(index.size == 2) { "Index dimension mismatch. Expected 2 but found ${index.size}" }
return get(index[0], index[1])
}
val rows: Buffer<Buffer<T>>
get() = VirtualBuffer(rowNum) { i ->
VirtualBuffer(colNum) { j -> get(i, j) }
}
public val rows: Buffer<Buffer<T>>
get() = VirtualBuffer(rowNum) { i -> VirtualBuffer(colNum) { j -> get(i, j) } }
val columns: Buffer<Buffer<T>>
get() = VirtualBuffer(colNum) { j ->
VirtualBuffer(rowNum) { i -> get(i, j) }
}
public val columns: Buffer<Buffer<T>>
get() = VirtualBuffer(colNum) { j -> VirtualBuffer(rowNum) { i -> get(i, j) } }
override fun elements(): Sequence<Pair<IntArray, T>> = sequence {
for (i in (0 until rowNum)) {
for (j in (0 until colNum)) {
yield(intArrayOf(i, j) to get(i, j))
}
}
for (i in (0 until rowNum))
for (j in (0 until colNum)) yield(intArrayOf(i, j) to get(i, j))
}
companion object
public companion object
}
/**
@ -49,10 +42,9 @@ private inline class Structure2DWrapper<T>(val structure: NDStructure<T>) : Stru
/**
* Represent a [NDStructure] as [Structure1D]. Throw error in case of dimension mismatch
*/
fun <T> NDStructure<T>.as2D(): Structure2D<T> = if (shape.size == 2) {
public fun <T> NDStructure<T>.as2D(): Structure2D<T> = if (shape.size == 2)
Structure2DWrapper(this)
} else {
else
error("Can't create 2d-structure from ${shape.size}d-structure")
}
typealias Matrix<T> = Structure2D<T>
public typealias Matrix<T> = Structure2D<T>

@ -7,20 +7,20 @@ import java.math.MathContext
/**
* A field over [BigInteger].
*/
object JBigIntegerField : Field<BigInteger> {
override val zero: BigInteger
public object JBigIntegerField : Field<BigInteger> {
public override val zero: BigInteger
get() = BigInteger.ZERO
override val one: BigInteger
public override val one: BigInteger
get() = BigInteger.ONE
override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b)
override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b)
override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b)
override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger())
override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b)
override operator fun BigInteger.unaryMinus(): BigInteger = negate()
public override fun number(value: Number): BigInteger = BigInteger.valueOf(value.toLong())
public override fun divide(a: BigInteger, b: BigInteger): BigInteger = a.div(b)
public override fun add(a: BigInteger, b: BigInteger): BigInteger = a.add(b)
public override operator fun BigInteger.minus(b: BigInteger): BigInteger = subtract(b)
public override fun multiply(a: BigInteger, k: Number): BigInteger = a.multiply(k.toInt().toBigInteger())
public override fun multiply(a: BigInteger, b: BigInteger): BigInteger = a.multiply(b)
public override operator fun BigInteger.unaryMinus(): BigInteger = negate()
}
/**
@ -28,32 +28,32 @@ object JBigIntegerField : Field<BigInteger> {
*
* @property mathContext the [MathContext] to use.
*/
abstract class JBigDecimalFieldBase internal constructor(val mathContext: MathContext = MathContext.DECIMAL64) :
public abstract class JBigDecimalFieldBase internal constructor(public val mathContext: MathContext = MathContext.DECIMAL64) :
Field<BigDecimal>,
PowerOperations<BigDecimal> {
override val zero: BigDecimal
public override val zero: BigDecimal
get() = BigDecimal.ZERO
override val one: BigDecimal
public override val one: BigDecimal
get() = BigDecimal.ONE
override fun add(a: BigDecimal, b: BigDecimal): BigDecimal = a.add(b)
override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b)
override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
public override fun add(a: BigDecimal, b: BigDecimal): BigDecimal = a.add(b)
public override operator fun BigDecimal.minus(b: BigDecimal): BigDecimal = subtract(b)
public override fun number(value: Number): BigDecimal = BigDecimal.valueOf(value.toDouble())
override fun multiply(a: BigDecimal, k: Number): BigDecimal =
public override fun multiply(a: BigDecimal, k: Number): BigDecimal =
a.multiply(k.toDouble().toBigDecimal(mathContext), mathContext)
override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext)
override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext)
override fun power(arg: BigDecimal, pow: Number): BigDecimal = arg.pow(pow.toInt(), mathContext)
override fun sqrt(arg: BigDecimal): BigDecimal = arg.sqrt(mathContext)
override operator fun BigDecimal.unaryMinus(): BigDecimal = negate(mathContext)
public override fun multiply(a: BigDecimal, b: BigDecimal): BigDecimal = a.multiply(b, mathContext)
public override fun divide(a: BigDecimal, b: BigDecimal): BigDecimal = a.divide(b, mathContext)
public override fun power(arg: BigDecimal, pow: Number): BigDecimal = arg.pow(pow.toInt(), mathContext)
public override fun sqrt(arg: BigDecimal): BigDecimal = arg.sqrt(mathContext)
public override operator fun BigDecimal.unaryMinus(): BigDecimal = negate(mathContext)
}
/**
* A field over [BigDecimal].
*/
class JBigDecimalField(mathContext: MathContext = MathContext.DECIMAL64) : JBigDecimalFieldBase(mathContext) {
companion object : JBigDecimalFieldBase()
public class JBigDecimalField(mathContext: MathContext = MathContext.DECIMAL64) : JBigDecimalFieldBase(mathContext) {
public companion object : JBigDecimalFieldBase()
}

@ -1,12 +1,8 @@
plugins {
id("scientifik.mpp")
//id("scientifik.atomic")
}
plugins { id("ru.mipt.npm.mpp") }
kotlin.sourceSets {
all {
with(languageSettings) {
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
useExperimentalAnnotation("kotlinx.coroutines.InternalCoroutinesApi")
useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
useExperimentalAnnotation("kotlinx.coroutines.FlowPreview")
@ -16,15 +12,7 @@ kotlin.sourceSets {
commonMain {
dependencies {
api(project(":kmath-core"))
api("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Scientifik.coroutinesVersion}")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion}")
}
}
jvmMain {
dependencies { api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Scientifik.coroutinesVersion}") }
}
jsMain {
dependencies { api("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:${Scientifik.coroutinesVersion}") }
}
}

@ -3,10 +3,10 @@ package scientifik.kmath.chains
/**
* Performance optimized chain for integer values
*/
abstract class BlockingIntChain : Chain<Int> {
abstract fun nextInt(): Int
public abstract class BlockingIntChain : Chain<Int> {
public abstract fun nextInt(): Int
override suspend fun next(): Int = nextInt()
fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() }
public fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() }
}

@ -3,10 +3,10 @@ package scientifik.kmath.chains
/**
* Performance optimized chain for real values
*/
abstract class BlockingRealChain : Chain<Double> {
abstract fun nextDouble(): Double
public abstract class BlockingRealChain : Chain<Double> {
public abstract fun nextDouble(): Double
override suspend fun next(): Double = nextDouble()
fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() }
public fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() }
}

@ -26,47 +26,44 @@ import kotlinx.coroutines.sync.withLock
* A not-necessary-Markov chain of some type
* @param R - the chain element type
*/
interface Chain<out R> : Flow<R> {
public interface Chain<out R> : Flow<R> {
/**
* Generate next value, changing state if needed
*/
suspend fun next(): R
public suspend fun next(): R
/**
* Create a copy of current chain state. Consuming resulting chain does not affect initial chain
*/
fun fork(): Chain<R>
public fun fork(): Chain<R>
override suspend fun collect(collector: FlowCollector<R>): Unit =
flow { while (true) emit(next()) }.collect(collector)
companion object
public companion object
}
fun <T> Iterator<T>.asChain(): Chain<T> = SimpleChain { next() }
fun <T> Sequence<T>.asChain(): Chain<T> = iterator().asChain()
public fun <T> Iterator<T>.asChain(): Chain<T> = SimpleChain { next() }
public fun <T> Sequence<T>.asChain(): Chain<T> = iterator().asChain()
/**
* A simple chain of independent tokens
*/
class SimpleChain<out R>(private val gen: suspend () -> R) : Chain<R> {
override suspend fun next(): R = gen()
override fun fork(): Chain<R> = this
public class SimpleChain<out R>(private val gen: suspend () -> R) : Chain<R> {
public override suspend fun next(): R = gen()
public override fun fork(): Chain<R> = this
}
/**
* A stateless Markov chain
*/
class MarkovChain<out R : Any>(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain<R> {
private val mutex = Mutex()
public class MarkovChain<out R : Any>(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain<R> {
private val mutex: Mutex = Mutex()
private var value: R? = null
fun value(): R? = value
public fun value(): R? = value
override suspend fun next(): R {
public override suspend fun next(): R {
mutex.withLock {
val newValue = gen(value ?: seed())
value = newValue
@ -74,9 +71,7 @@ class MarkovChain<out R : Any>(private val seed: suspend () -> R, private val ge
}
}
override fun fork(): Chain<R> {
return MarkovChain(seed = { value ?: seed() }, gen = gen)
}
public override fun fork(): Chain<R> = MarkovChain(seed = { value ?: seed() }, gen = gen)
}
/**
@ -84,19 +79,18 @@ class MarkovChain<out R : Any>(private val seed: suspend () -> R, private val ge
* @param S - the state of the chain
* @param forkState - the function to copy current state without modifying it
*/
class StatefulChain<S, out R>(
public class StatefulChain<S, out R>(
private val state: S,
private val seed: S.() -> R,
private val forkState: ((S) -> S),
private val gen: suspend S.(R) -> R
) : Chain<R> {
private val mutex: Mutex = Mutex()
private var value: R? = null
fun value(): R? = value
public fun value(): R? = value
override suspend fun next(): R {
public override suspend fun next(): R {
mutex.withLock {
val newValue = state.gen(value ?: state.seed())
value = newValue
@ -104,25 +98,22 @@ class StatefulChain<S, out R>(
}
}
override fun fork(): Chain<R> = StatefulChain(forkState(state), seed, forkState, gen)
public override fun fork(): Chain<R> = StatefulChain(forkState(state), seed, forkState, gen)
}
/**
* A chain that repeats the same value
*/
class ConstantChain<out T>(val value: T) : Chain<T> {
override suspend fun next(): T = value
override fun fork(): Chain<T> {
return this
}
public class ConstantChain<out T>(public val value: T) : Chain<T> {
public override suspend fun next(): T = value
public override fun fork(): Chain<T> = this
}
/**
* Map the chain result using suspended transformation. Initial chain result can no longer be safely consumed
* since mapped chain consumes tokens. Accepts regular transformation function
*/
fun <T, R> Chain<T>.map(func: suspend (T) -> R): Chain<R> = object : Chain<R> {
public fun <T, R> Chain<T>.map(func: suspend (T) -> R): Chain<R> = object : Chain<R> {
override suspend fun next(): R = func(this@map.next())
override fun fork(): Chain<R> = this@map.fork().map(func)
}
@ -130,7 +121,7 @@ fun <T, R> Chain<T>.map(func: suspend (T) -> R): Chain<R> = object : Chain<R> {
/**
* [block] must be a pure function or at least not use external random variables, otherwise fork could be broken
*/
fun <T> Chain<T>.filter(block: (T) -> Boolean): Chain<T> = object : Chain<T> {
public fun <T> Chain<T>.filter(block: (T) -> Boolean): Chain<T> = object : Chain<T> {
override suspend fun next(): T {
var next: T
@ -146,23 +137,26 @@ fun <T> Chain<T>.filter(block: (T) -> Boolean): Chain<T> = object : Chain<T> {
/**
* Map the whole chain
*/
fun <T, R> Chain<T>.collect(mapper: suspend (Chain<T>) -> R): Chain<R> = object : Chain<R> {
public fun <T, R> Chain<T>.collect(mapper: suspend (Chain<T>) -> R): Chain<R> = object : Chain<R> {
override suspend fun next(): R = mapper(this@collect)
override fun fork(): Chain<R> = this@collect.fork().collect(mapper)
}
fun <T, S, R> Chain<T>.collectWithState(state: S, stateFork: (S) -> S, mapper: suspend S.(Chain<T>) -> R): Chain<R> =
object : Chain<R> {
override suspend fun next(): R = state.mapper(this@collectWithState)
public fun <T, S, R> Chain<T>.collectWithState(
state: S,
stateFork: (S) -> S,
mapper: suspend S.(Chain<T>) -> R
): Chain<R> = object : Chain<R> {
override suspend fun next(): R = state.mapper(this@collectWithState)
override fun fork(): Chain<R> =
this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper)
}
override fun fork(): Chain<R> =
this@collectWithState.fork().collectWithState(stateFork(state), stateFork, mapper)
}
/**
* Zip two chains together using given transformation
*/
fun <T, U, R> Chain<T>.zip(other: Chain<U>, block: suspend (T, U) -> R): Chain<R> = object : Chain<R> {
public fun <T, U, R> Chain<T>.zip(other: Chain<U>, block: suspend (T, U) -> R): Chain<R> = object : Chain<R> {
override suspend fun next(): R = block(this@zip.next(), other.next())
override fun fork(): Chain<R> = this@zip.fork().zip(other.fork(), block)
}

@ -3,20 +3,19 @@ package scientifik.kmath.chains
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.runningReduce
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.scanReduce
import scientifik.kmath.operations.Space
import scientifik.kmath.operations.SpaceOperations
import scientifik.kmath.operations.invoke
@ExperimentalCoroutinesApi
fun <T> Flow<T>.cumulativeSum(space: SpaceOperations<T>): Flow<T> = space {
scanReduce { sum: T, element: T -> sum + element }
}
public fun <T> Flow<T>.cumulativeSum(space: SpaceOperations<T>): Flow<T> =
space { runningReduce { sum, element -> sum + element } }
@ExperimentalCoroutinesApi
fun <T> Flow<T>.mean(space: Space<T>): Flow<T> = space {
class Accumulator(var sum: T, var num: Int)
public fun <T> Flow<T>.mean(space: Space<T>): Flow<T> = space {
data class Accumulator(var sum: T, var num: Int)
scan(Accumulator(zero, 0)) { sum, element ->
sum.apply {

@ -3,9 +3,8 @@ package scientifik.kmath.coroutines
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.flow.*
import kotlin.contracts.contract
val Dispatchers.Math: CoroutineDispatcher
public val Dispatchers.Math: CoroutineDispatcher
get() = Default
/**
@ -15,31 +14,25 @@ internal class LazyDeferred<T>(val dispatcher: CoroutineDispatcher, val block: s
private var deferred: Deferred<T>? = null
internal fun start(scope: CoroutineScope) {
if (deferred == null) {
deferred = scope.async(dispatcher, block = block)
}
if (deferred == null) deferred = scope.async(dispatcher, block = block)
}
suspend fun await(): T = deferred?.await() ?: error("Coroutine not started")
}
class AsyncFlow<T> internal constructor(internal val deferredFlow: Flow<LazyDeferred<T>>) : Flow<T> {
override suspend fun collect(collector: FlowCollector<T>) {
deferredFlow.collect { collector.emit((it.await())) }
}
public class AsyncFlow<T> internal constructor(internal val deferredFlow: Flow<LazyDeferred<T>>) : Flow<T> {
override suspend fun collect(collector: FlowCollector<T>): Unit = deferredFlow.collect { collector.emit((it.await())) }
}
fun <T, R> Flow<T>.async(
public fun <T, R> Flow<T>.async(
dispatcher: CoroutineDispatcher = Dispatchers.Default,
block: suspend CoroutineScope.(T) -> R
): AsyncFlow<R> {
val flow = map {
LazyDeferred(dispatcher) { block(it) }
}
val flow = map { LazyDeferred(dispatcher) { block(it) } }
return AsyncFlow(flow)
}
fun <T, R> AsyncFlow<T>.map(action: (T) -> R): AsyncFlow<R> =
public fun <T, R> AsyncFlow<T>.map(action: (T) -> R): AsyncFlow<R> =
AsyncFlow(deferredFlow.map { input ->
//TODO add function composition
LazyDeferred(input.dispatcher) {
@ -48,7 +41,7 @@ fun <T, R> AsyncFlow<T>.map(action: (T) -> R): AsyncFlow<R> =
}
})
suspend fun <T> AsyncFlow<T>.collect(concurrency: Int, collector: FlowCollector<T>) {
public suspend fun <T> AsyncFlow<T>.collect(concurrency: Int, collector: FlowCollector<T>) {
require(concurrency >= 1) { "Buffer size should be more than 1, but was $concurrency" }
coroutineScope {
@ -76,18 +69,14 @@ suspend fun <T> AsyncFlow<T>.collect(concurrency: Int, collector: FlowCollector<
}
}
suspend inline fun <T> AsyncFlow<T>.collect(concurrency: Int, crossinline action: suspend (value: T) -> Unit) {
contract { callsInPlace(action) }
public suspend inline fun <T> AsyncFlow<T>.collect(
concurrency: Int,
crossinline action: suspend (value: T) -> Unit
): Unit = collect(concurrency, object : FlowCollector<T> {
override suspend fun emit(value: T): Unit = action(value)
})
collect(concurrency, object : FlowCollector<T> {
override suspend fun emit(value: T): Unit = action(value)
})
}
inline fun <T, R> Flow<T>.mapParallel(
public inline fun <T, R> Flow<T>.mapParallel(
dispatcher: CoroutineDispatcher = Dispatchers.Default,
crossinline transform: suspend (T) -> R
): Flow<R> {
contract { callsInPlace(transform) }
return flatMapMerge { value -> flow { emit(transform(value)) } }.flowOn(dispatcher)
}
): Flow<R> = flatMapMerge { value -> flow { emit(transform(value)) } }.flowOn(dispatcher)

@ -11,18 +11,18 @@ import scientifik.kmath.structures.asBuffer
/**
* Create a [Flow] from buffer
*/
fun <T> Buffer<T>.asFlow(): Flow<T> = iterator().asFlow()
public fun <T> Buffer<T>.asFlow(): Flow<T> = iterator().asFlow()
/**
* Flat map a [Flow] of [Buffer] into continuous [Flow] of elements
*/
@FlowPreview
fun <T> Flow<Buffer<out T>>.spread(): Flow<T> = flatMapConcat { it.asFlow() }
public fun <T> Flow<Buffer<out T>>.spread(): Flow<T> = flatMapConcat { it.asFlow() }
/**
* Collect incoming flow into fixed size chunks
*/
fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>): Flow<Buffer<T>> = flow {
public fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>): Flow<Buffer<T>> = flow {
require(bufferSize > 0) { "Resulting chunk size must be more than zero" }
val list = ArrayList<T>(bufferSize)
var counter = 0
@ -30,6 +30,7 @@ fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>): Flow<
this@chunked.collect { element ->
list.add(element)
counter++
if (counter == bufferSize) {
val buffer = bufferFactory(bufferSize) { list[it] }
emit(buffer)
@ -37,22 +38,19 @@ fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>): Flow<
counter = 0
}
}
if (counter > 0) {
emit(bufferFactory(counter) { list[it] })
}
if (counter > 0) emit(bufferFactory(counter) { list[it] })
}
/**
* Specialized flow chunker for real buffer
*/
fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
public fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
require(bufferSize > 0) { "Resulting chunk size must be more than zero" }
if (this@chunked is BlockingRealChain) {
//performance optimization for blocking primitive chain
while (true) {
emit(nextBlock(bufferSize).asBuffer())
}
// performance optimization for blocking primitive chain
while (true) emit(nextBlock(bufferSize).asBuffer())
} else {
val array = DoubleArray(bufferSize)
var counter = 0
@ -60,15 +58,15 @@ fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
this@chunked.collect { element ->
array[counter] = element
counter++
if (counter == bufferSize) {
val buffer = RealBuffer(array)
emit(buffer)
counter = 0
}
}
if (counter > 0) {
emit(RealBuffer(counter) { array[it] })
}
if (counter > 0) emit(RealBuffer(counter) { array[it] })
}
}
@ -76,9 +74,10 @@ fun Flow<Double>.chunked(bufferSize: Int): Flow<RealBuffer> = flow {
* Map a flow to a moving window buffer. The window step is one.
* In order to get different steps, one could use skip operation.
*/
fun <T> Flow<T>.windowed(window: Int): Flow<Buffer<T>> = flow {
public fun <T> Flow<T>.windowed(window: Int): Flow<Buffer<T>> = flow {
require(window > 1) { "Window size must be more than one" }
val ringBuffer = RingBuffer.boxing<T>(window)
this@windowed.collect { element ->
ringBuffer.push(element)
emit(ringBuffer.snapshot())

@ -10,28 +10,28 @@ import scientifik.kmath.structures.VirtualBuffer
* Thread-safe ring buffer
*/
@Suppress("UNCHECKED_CAST")
class RingBuffer<T>(
public class RingBuffer<T>(
private val buffer: MutableBuffer<T?>,
private var startIndex: Int = 0,
size: Int = 0
) : Buffer<T> {
private val mutex: Mutex = Mutex()
override var size: Int = size
public override var size: Int = size
private set
override operator fun get(index: Int): T {
public override operator fun get(index: Int): T {
require(index >= 0) { "Index must be positive" }
require(index < size) { "Index $index is out of circular buffer size $size" }
return buffer[startIndex.forward(index)] as T
}
fun isFull(): Boolean = size == buffer.size
public fun isFull(): Boolean = size == buffer.size
/**
* Iterator could provide wrong results if buffer is changed in initialization (iteration is safe)
*/
override operator fun iterator(): Iterator<T> = object : AbstractIterator<T>() {
public override operator fun iterator(): Iterator<T> = object : AbstractIterator<T>() {
private var count = size
private var index = startIndex
val copy = buffer.copy()
@ -48,23 +48,17 @@ class RingBuffer<T>(
/**
* A safe snapshot operation
*/
suspend fun snapshot(): Buffer<T> {
public suspend fun snapshot(): Buffer<T> {
mutex.withLock {
val copy = buffer.copy()
return VirtualBuffer(size) { i ->
copy[startIndex.forward(i)] as T
}
return VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T }
}
}
suspend fun push(element: T) {
public suspend fun push(element: T) {
mutex.withLock {
buffer[startIndex.forward(size)] = element
if (isFull()) {
startIndex++
} else {
size++
}
if (isFull()) startIndex++ else size++
}
}
@ -72,8 +66,8 @@ class RingBuffer<T>(
@Suppress("NOTHING_TO_INLINE")
private inline fun Int.forward(n: Int): Int = (this + n) % (buffer.size)
companion object {
inline fun <reified T : Any> build(size: Int, empty: T): RingBuffer<T> {
public companion object {
public inline fun <reified T : Any> build(size: Int, empty: T): RingBuffer<T> {
val buffer = MutableBuffer.auto(size) { empty } as MutableBuffer<T?>
return RingBuffer(buffer)
}
@ -81,7 +75,7 @@ class RingBuffer<T>(
/**
* Slow yet universal buffer
*/
fun <T> boxing(size: Int): RingBuffer<T> {
public fun <T> boxing(size: Int): RingBuffer<T> {
val buffer: MutableBuffer<T?> = MutableBuffer.boxing(size) { null }
return RingBuffer(buffer)
}

@ -5,13 +5,12 @@ import kotlinx.coroutines.runBlocking
/**
* Represent a chain as regular iterator (uses blocking calls)
*/
operator fun <R> Chain<R>.iterator(): Iterator<R> = object : Iterator<R> {
public operator fun <R> Chain<R>.iterator(): Iterator<R> = object : Iterator<R> {
override fun hasNext(): Boolean = true
override fun next(): R = runBlocking { next() }
}
/**
* Represent a chain as a sequence
*/
fun <R> Chain<R>.asSequence(): Sequence<R> = Sequence { this@asSequence.iterator() }
public fun <R> Chain<R>.asSequence(): Sequence<R> = Sequence { this@asSequence.iterator() }

@ -3,38 +3,31 @@ package scientifik.kmath.structures
import kotlinx.coroutines.*
import scientifik.kmath.coroutines.Math
class LazyNDStructure<T>(
val scope: CoroutineScope,
override val shape: IntArray,
val function: suspend (IntArray) -> T
public class LazyNDStructure<T>(
public val scope: CoroutineScope,
public override val shape: IntArray,
public val function: suspend (IntArray) -> T
) : NDStructure<T> {
private val cache: MutableMap<IntArray, Deferred<T>> = hashMapOf()
fun deferred(index: IntArray): Deferred<T> = cache.getOrPut(index) {
scope.async(context = Dispatchers.Math) {
function(index)
}
public fun deferred(index: IntArray): Deferred<T> = cache.getOrPut(index) {
scope.async(context = Dispatchers.Math) { function(index) }
}
suspend fun await(index: IntArray): T = deferred(index).await()
public suspend fun await(index: IntArray): T = deferred(index).await()
public override operator fun get(index: IntArray): T = runBlocking { deferred(index).await() }
override operator fun get(index: IntArray): T = runBlocking {
deferred(index).await()
}
override fun elements(): Sequence<Pair<IntArray, T>> {
public override fun elements(): Sequence<Pair<IntArray, T>> {
val strides = DefaultStrides(shape)
val res = runBlocking {
strides.indices().toList().map { index -> index to await(index) }
}
val res = runBlocking { strides.indices().toList().map { index -> index to await(index) } }
return res.asSequence()
}
override fun equals(other: Any?): Boolean {
public override fun equals(other: Any?): Boolean {
return NDStructure.equals(this, other as? NDStructure<*> ?: return false)
}
override fun hashCode(): Int {
public override fun hashCode(): Int {
var result = scope.hashCode()
result = 31 * result + shape.contentHashCode()
result = 31 * result + function.hashCode()
@ -43,21 +36,21 @@ class LazyNDStructure<T>(
}
}
fun <T> NDStructure<T>.deferred(index: IntArray): Deferred<T> =
if (this is LazyNDStructure<T>) this.deferred(index) else CompletableDeferred(get(index))
public fun <T> NDStructure<T>.deferred(index: IntArray): Deferred<T> =
if (this is LazyNDStructure<T>) deferred(index) else CompletableDeferred(get(index))
suspend fun <T> NDStructure<T>.await(index: IntArray): T =
if (this is LazyNDStructure<T>) this.await(index) else get(index)
public suspend fun <T> NDStructure<T>.await(index: IntArray): T =
if (this is LazyNDStructure<T>) await(index) else get(index)
/**
* PENDING would benefit from KEEP-176
*/
inline fun <T, R> NDStructure<T>.mapAsyncIndexed(
public inline fun <T, R> NDStructure<T>.mapAsyncIndexed(
scope: CoroutineScope,
crossinline function: suspend (T, index: IntArray) -> R
): LazyNDStructure<R> = LazyNDStructure(scope, shape) { index -> function(get(index), index) }
inline fun <T, R> NDStructure<T>.mapAsync(
public inline fun <T, R> NDStructure<T>.mapAsync(
scope: CoroutineScope,
crossinline function: suspend (T) -> R
): LazyNDStructure<R> = LazyNDStructure(scope, shape) { index -> function(get(index)) }

@ -14,7 +14,7 @@ import kotlin.test.Test
@ExperimentalCoroutinesApi
@InternalCoroutinesApi
@FlowPreview
class BufferFlowTest {
internal class BufferFlowTest {
val dispatcher: CoroutineDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
@Test

@ -6,7 +6,7 @@ import scientifik.kmath.structures.asSequence
import kotlin.test.Test
import kotlin.test.assertEquals
class RingBufferTest {
internal class RingBufferTest {
@Test
fun push() {
val buffer = RingBuffer.build(20, Double.NaN)

@ -1,8 +1,6 @@
plugins {
id("scientifik.mpp")
}
plugins { id("ru.mipt.npm.mpp") }
description = "A proof of concept module for adding typ-safe dimensions to structures"
description = "A proof of concept module for adding type-safe dimensions to structures"
kotlin.sourceSets {
commonMain {
@ -11,9 +9,9 @@ kotlin.sourceSets {
}
}
jvmMain{
dependencies{
jvmMain {
dependencies {
api(kotlin("reflect"))
}
}
}
}

@ -6,30 +6,28 @@ import kotlin.reflect.KClass
* An abstract class which is not used in runtime. Designates a size of some structure.
* Could be replaced later by fully inline constructs
*/
interface Dimension {
public interface Dimension {
public val dim: UInt
val dim: UInt
companion object {
}
public companion object
}
fun <D : Dimension> KClass<D>.dim(): UInt = Dimension.resolve(this).dim
public fun <D : Dimension> KClass<D>.dim(): UInt = Dimension.resolve(this).dim
expect fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D
public expect fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D
expect fun Dimension.Companion.of(dim: UInt): Dimension
public expect fun Dimension.Companion.of(dim: UInt): Dimension
inline fun <reified D : Dimension> Dimension.Companion.dim(): UInt = D::class.dim()
public inline fun <reified D : Dimension> Dimension.Companion.dim(): UInt = D::class.dim()
object D1 : Dimension {
public object D1 : Dimension {
override val dim: UInt get() = 1U
}
object D2 : Dimension {
public object D2 : Dimension {
override val dim: UInt get() = 2U
}
object D3 : Dimension {
public object D3 : Dimension {
override val dim: UInt get() = 3U
}

@ -13,35 +13,36 @@ import scientifik.kmath.structures.Structure2D
/**
* A matrix with compile-time controlled dimension
*/
interface DMatrix<T, R : Dimension, C : Dimension> : Structure2D<T> {
companion object {
public interface DMatrix<T, R : Dimension, C : Dimension> : Structure2D<T> {
public companion object {
/**
* Coerces a regular matrix to a matrix with type-safe dimensions and throws a error if coercion failed
*/
inline fun <T, reified R : Dimension, reified C : Dimension> coerce(structure: Structure2D<T>): DMatrix<T, R, C> {
if (structure.rowNum != Dimension.dim<R>().toInt()) {
error("Row number mismatch: expected ${Dimension.dim<R>()} but found ${structure.rowNum}")
public inline fun <T, reified R : Dimension, reified C : Dimension> coerce(structure: Structure2D<T>): DMatrix<T, R, C> {
require(structure.rowNum == Dimension.dim<R>().toInt()) {
"Row number mismatch: expected ${Dimension.dim<R>()} but found ${structure.rowNum}"
}
if (structure.colNum != Dimension.dim<C>().toInt()) {
error("Column number mismatch: expected ${Dimension.dim<C>()} but found ${structure.colNum}")
require(structure.colNum == Dimension.dim<C>().toInt()) {
"Column number mismatch: expected ${Dimension.dim<C>()} but found ${structure.colNum}"
}
return DMatrixWrapper(structure)
}
/**
* The same as [coerce] but without dimension checks. Use with caution
* The same as [DMatrix.coerce] but without dimension checks. Use with caution
*/
fun <T, R : Dimension, C : Dimension> coerceUnsafe(structure: Structure2D<T>): DMatrix<T, R, C> {
return DMatrixWrapper(structure)
}
public fun <T, R : Dimension, C : Dimension> coerceUnsafe(structure: Structure2D<T>): DMatrix<T, R, C> =
DMatrixWrapper(structure)
}
}
/**
* An inline wrapper for a Matrix
*/
inline class DMatrixWrapper<T, R : Dimension, C : Dimension>(
val structure: Structure2D<T>
public inline class DMatrixWrapper<T, R : Dimension, C : Dimension>(
public val structure: Structure2D<T>
) : DMatrix<T, R, C> {
override val shape: IntArray get() = structure.shape
override operator fun get(i: Int, j: Int): T = structure[i, j]
@ -50,25 +51,24 @@ inline class DMatrixWrapper<T, R : Dimension, C : Dimension>(
/**
* Dimension-safe point
*/
interface DPoint<T, D : Dimension> : Point<T> {
companion object {
inline fun <T, reified D : Dimension> coerce(point: Point<T>): DPoint<T, D> {
if (point.size != Dimension.dim<D>().toInt()) {
error("Vector dimension mismatch: expected ${Dimension.dim<D>()}, but found ${point.size}")
public interface DPoint<T, D : Dimension> : Point<T> {
public companion object {
public inline fun <T, reified D : Dimension> coerce(point: Point<T>): DPoint<T, D> {
require(point.size == Dimension.dim<D>().toInt()) {
"Vector dimension mismatch: expected ${Dimension.dim<D>()}, but found ${point.size}"
}
return DPointWrapper(point)
}
fun <T, D : Dimension> coerceUnsafe(point: Point<T>): DPoint<T, D> {
return DPointWrapper(point)
}
public fun <T, D : Dimension> coerceUnsafe(point: Point<T>): DPoint<T, D> = DPointWrapper(point)
}
}
/**
* Dimension-safe point wrapper
*/
inline class DPointWrapper<T, D : Dimension>(val point: Point<T>) :
public inline class DPointWrapper<T, D : Dimension>(public val point: Point<T>) :
DPoint<T, D> {
override val size: Int get() = point.size
@ -81,16 +81,15 @@ inline class DPointWrapper<T, D : Dimension>(val point: Point<T>) :
/**
* Basic operations on dimension-safe matrices. Operates on [Matrix]
*/
inline class DMatrixContext<T : Any, Ri : Ring<T>>(val context: GenericMatrixContext<T, Ri>) {
public inline class DMatrixContext<T : Any, Ri : Ring<T>>(public val context: GenericMatrixContext<T, Ri>) {
public inline fun <reified R : Dimension, reified C : Dimension> Matrix<T>.coerce(): DMatrix<T, R, C> {
require(rowNum == Dimension.dim<R>().toInt()) {
"Row number mismatch: expected ${Dimension.dim<R>()} but found $rowNum"
}
inline fun <reified R : Dimension, reified C : Dimension> Matrix<T>.coerce(): DMatrix<T, R, C> {
check(
rowNum == Dimension.dim<R>().toInt()
) { "Row number mismatch: expected ${Dimension.dim<R>()} but found $rowNum" }
check(
colNum == Dimension.dim<C>().toInt()
) { "Column number mismatch: expected ${Dimension.dim<C>()} but found $colNum" }
require(colNum == Dimension.dim<C>().toInt()) {
"Column number mismatch: expected ${Dimension.dim<C>()} but found $colNum"
}
return DMatrix.coerceUnsafe(this)
}
@ -98,13 +97,13 @@ inline class DMatrixContext<T : Any, Ri : Ring<T>>(val context: GenericMatrixCon
/**
* Produce a matrix with this context and given dimensions
*/
inline fun <reified R : Dimension, reified C : Dimension> produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix<T, R, C> {
public inline fun <reified R : Dimension, reified C : Dimension> produce(noinline initializer: (i: Int, j: Int) -> T): DMatrix<T, R, C> {
val rows = Dimension.dim<R>()
val cols = Dimension.dim<C>()
return context.produce(rows.toInt(), cols.toInt(), initializer).coerce<R, C>()
}
inline fun <reified D : Dimension> point(noinline initializer: (Int) -> T): DPoint<T, D> {
public inline fun <reified D : Dimension> point(noinline initializer: (Int) -> T): DPoint<T, D> {
val size = Dimension.dim<D>()
return DPoint.coerceUnsafe(
@ -115,43 +114,43 @@ inline class DMatrixContext<T : Any, Ri : Ring<T>>(val context: GenericMatrixCon
)
}
inline infix fun <reified R1 : Dimension, reified C1 : Dimension, reified C2 : Dimension> DMatrix<T, R1, C1>.dot(
public inline infix fun <reified R1 : Dimension, reified C1 : Dimension, reified C2 : Dimension> DMatrix<T, R1, C1>.dot(
other: DMatrix<T, C1, C2>
): DMatrix<T, R1, C2> = context { this@dot dot other }.coerce()
inline infix fun <reified R : Dimension, reified C : Dimension> DMatrix<T, R, C>.dot(vector: DPoint<T, C>): DPoint<T, R> =
public inline infix fun <reified R : Dimension, reified C : Dimension> DMatrix<T, R, C>.dot(vector: DPoint<T, C>): DPoint<T, R> =
DPoint.coerceUnsafe(context { this@dot dot vector })
inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, R, C>.times(value: T): DMatrix<T, R, C> =
public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, R, C>.times(value: T): DMatrix<T, R, C> =
context { this@times.times(value) }.coerce()
inline operator fun <reified R : Dimension, reified C : Dimension> T.times(m: DMatrix<T, R, C>): DMatrix<T, R, C> =
public inline operator fun <reified R : Dimension, reified C : Dimension> T.times(m: DMatrix<T, R, C>): DMatrix<T, R, C> =
m * this
inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.plus(other: DMatrix<T, C, R>): DMatrix<T, C, R> =
public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.plus(other: DMatrix<T, C, R>): DMatrix<T, C, R> =
context { this@plus + other }.coerce()
inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.minus(other: DMatrix<T, C, R>): DMatrix<T, C, R> =
public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.minus(other: DMatrix<T, C, R>): DMatrix<T, C, R> =
context { this@minus + other }.coerce()
inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.unaryMinus(): DMatrix<T, C, R> =
public inline operator fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.unaryMinus(): DMatrix<T, C, R> =
context { this@unaryMinus.unaryMinus() }.coerce()
inline fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.transpose(): DMatrix<T, R, C> =
public inline fun <reified R : Dimension, reified C : Dimension> DMatrix<T, C, R>.transpose(): DMatrix<T, R, C> =
context { (this@transpose as Matrix<T>).transpose() }.coerce()
/**
* A square unit matrix
*/
inline fun <reified D : Dimension> one(): DMatrix<T, D, D> = produce { i, j ->
public inline fun <reified D : Dimension> one(): DMatrix<T, D, D> = produce { i, j ->
if (i == j) context.elementContext.one else context.elementContext.zero
}
inline fun <reified R : Dimension, reified C : Dimension> zero(): DMatrix<T, R, C> = produce { _, _ ->
public inline fun <reified R : Dimension, reified C : Dimension> zero(): DMatrix<T, R, C> = produce { _, _ ->
context.elementContext.zero
}
companion object {
val real: DMatrixContext<Double, RealField> = DMatrixContext(MatrixContext.real)
public companion object {
public val real: DMatrixContext<Double, RealField> = DMatrixContext(MatrixContext.real)
}
}

@ -5,7 +5,7 @@ import scientifik.kmath.dimensions.D3
import scientifik.kmath.dimensions.DMatrixContext
import kotlin.test.Test
class DMatrixContextTest {
internal class DMatrixContextTest {
@Test
fun testDimensionSafeMatrix() {
val res = with(DMatrixContext.real) {
@ -26,4 +26,4 @@ class DMatrixContextTest {
m1.transpose() + m2
}
}
}
}

@ -2,21 +2,17 @@ package scientifik.kmath.dimensions
import kotlin.reflect.KClass
private val dimensionMap = hashMapOf<UInt, Dimension>(
1u to D1,
2u to D2,
3u to D3
)
private val dimensionMap: MutableMap<UInt, Dimension> = hashMapOf(1u to D1, 2u to D2, 3u to D3)
@Suppress("UNCHECKED_CAST")
actual fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D {
return dimensionMap.entries.find { it.value::class == type }?.value as? D ?: error("Can't resolve dimension $type")
}
public actual fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D = dimensionMap
.entries
.map(MutableMap.MutableEntry<UInt, Dimension>::value)
.find { it::class == type } as? D
?: error("Can't resolve dimension $type")
actual fun Dimension.Companion.of(dim: UInt): Dimension {
return dimensionMap.getOrPut(dim) {
object : Dimension {
override val dim: UInt get() = dim
}
public actual fun Dimension.Companion.of(dim: UInt): Dimension = dimensionMap.getOrPut(dim) {
object : Dimension {
override val dim: UInt get() = dim
}
}
}

@ -2,17 +2,15 @@ package scientifik.kmath.dimensions
import kotlin.reflect.KClass
actual fun <D:Dimension> Dimension.Companion.resolve(type: KClass<D>): D{
return type.objectInstance ?: error("No object instance for dimension class")
}
public actual fun <D : Dimension> Dimension.Companion.resolve(type: KClass<D>): D =
type.objectInstance ?: error("No object instance for dimension class")
actual fun Dimension.Companion.of(dim: UInt): Dimension{
return when(dim){
1u -> D1
2u -> D2
3u -> D3
else -> object : Dimension {
override val dim: UInt get() = dim
}
public actual fun Dimension.Companion.of(dim: UInt): Dimension = when (dim) {
1u -> D1
2u -> D2
3u -> D3
else -> object : Dimension {
override val dim: UInt get() = dim
}
}

@ -1,6 +1,7 @@
plugins { id("scientifik.mpp") }
plugins { id("ru.mipt.npm.mpp") }
kotlin.sourceSets {
all { languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") }
commonMain { dependencies { api(project(":kmath-core")) } }
kotlin.sourceSets.commonMain {
dependencies {
api(project(":kmath-core"))
}
}

@ -12,39 +12,34 @@ import scientifik.kmath.structures.asBuffer
import scientifik.kmath.structures.asIterable
import kotlin.math.sqrt
typealias RealPoint = Point<Double>
public typealias RealPoint = Point<Double>
fun DoubleArray.asVector(): RealVector = RealVector(this.asBuffer())
fun List<Double>.asVector(): RealVector = RealVector(this.asBuffer())
public fun DoubleArray.asVector(): RealVector = RealVector(asBuffer())
public fun List<Double>.asVector(): RealVector = RealVector(asBuffer())
object VectorL2Norm : Norm<Point<out Number>, Double> {
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble { it.toDouble() })
public object VectorL2Norm : Norm<Point<out Number>, Double> {
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble))
}
inline class RealVector(private val point: Point<Double>) :
public inline class RealVector(private val point: Point<Double>) :
SpaceElement<RealPoint, RealVector, VectorSpace<Double, RealField>>, RealPoint {
public override val size: Int get() = point.size
public override val context: VectorSpace<Double, RealField> get() = space(point.size)
override val context: VectorSpace<Double, RealField> get() = space(point.size)
public override fun unwrap(): RealPoint = point
public override fun RealPoint.wrap(): RealVector = RealVector(this)
public override operator fun get(index: Int): Double = point[index]
public override operator fun iterator(): Iterator<Double> = point.iterator()
override fun unwrap(): RealPoint = point
override fun RealPoint.wrap(): RealVector = RealVector(this)
override val size: Int get() = point.size
override operator fun get(index: Int): Double = point[index]
override operator fun iterator(): Iterator<Double> = point.iterator()
companion object {
public companion object {
private val spaceCache: MutableMap<Int, BufferVectorSpace<Double, RealField>> = hashMapOf()
inline operator fun invoke(dim: Int, initializer: (Int) -> Double): RealVector =
public inline operator fun invoke(dim: Int, initializer: (Int) -> Double): RealVector =
RealVector(RealBuffer(dim, initializer))
operator fun invoke(vararg values: Double): RealVector = values.asVector()
public operator fun invoke(vararg values: Double): RealVector = values.asVector()
fun space(dim: Int): BufferVectorSpace<Double, RealField> = spaceCache.getOrPut(dim) {
public fun space(dim: Int): BufferVectorSpace<Double, RealField> = spaceCache.getOrPut(dim) {
BufferVectorSpace(dim, RealField) { size, init -> Buffer.real(size, init) }
}
}

Some files were not shown because too many files have changed in this diff Show More