diff --git a/build.gradle.kts b/build.gradle.kts index 6f0478fc2..e5c4fc39b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,10 +1,14 @@ buildscript { - val kotlinVersion: String by rootProject.extra("1.3.20") - val ioVersion: String by rootProject.extra("0.1.2") - val coroutinesVersion: String by rootProject.extra("1.1.1") + extra["kotlinVersion"] = "1.3.20-eap-100" + extra["ioVersion"] = "0.1.2" + extra["coroutinesVersion"] = "1.1.0" + + val kotlinVersion: String by extra + val ioVersion: String by extra + val coroutinesVersion: String by extra repositories { - //maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlin-eap") jcenter() } @@ -24,7 +28,7 @@ allprojects { apply(plugin = "com.jfrog.artifactory") group = "scientifik" - version = "0.0.3-dev-4" + version = "0.0.3-dev-3" repositories { maven("https://dl.bintray.com/kotlin/kotlin-eap") diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/linear/CMMatrix.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/linear/CMMatrix.kt index 808b2768b..aed4f4bb1 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/linear/CMMatrix.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/linear/CMMatrix.kt @@ -4,16 +4,11 @@ import org.apache.commons.math3.linear.* import org.apache.commons.math3.linear.RealMatrix import org.apache.commons.math3.linear.RealVector -class CMMatrix(val origin: RealMatrix, features: Set? = null) : Matrix { +inline class CMMatrix(val origin: RealMatrix) : Matrix { override val rowNum: Int get() = origin.rowDimension override val colNum: Int get() = origin.columnDimension - override val features: Set = features ?: sequence { - if(origin is DiagonalMatrix) yield(DiagonalFeature) - }.toSet() - - override fun suggestFeature(vararg features: MatrixFeature) = - CMMatrix(origin, this.features + features) + override val features: Set get() = emptySet() override fun get(i: Int, j: Int): Double = origin.getEntry(i, j) } @@ -28,7 +23,7 @@ fun Matrix.toCM(): CMMatrix = if (this is CMMatrix) { fun RealMatrix.toMatrix() = CMMatrix(this) -class CMVector(val origin: RealVector) : Point { +inline class CMVector(val origin: RealVector) : Point { override val size: Int get() = origin.dimension override fun get(index: Int): Double = origin.getEntry(index) diff --git a/kmath-core/build.gradle b/kmath-core/build.gradle new file mode 100644 index 000000000..b1a6cccb5 --- /dev/null +++ b/kmath-core/build.gradle @@ -0,0 +1,50 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" +} + +kotlin { + jvm { + compilations["main"].kotlinOptions.jvmTarget = "1.8" + compilations["test"].kotlinOptions.jvmTarget = "1.8" + } + js() + + sourceSets { + commonMain { + dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } + commonTest { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-test-common' + implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common' + } + } + jvmMain { + dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + } + } + jvmTest { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-test' + implementation 'org.jetbrains.kotlin:kotlin-test-junit' + } + } + jsMain { + dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-js' + } + } + jsTest { + dependencies { + implementation 'org.jetbrains.kotlin:kotlin-test-js' + } + } +// mingwMain { +// } +// mingwTest { +// } + } +} diff --git a/kmath-core/build.gradle.kts b/kmath-core/build.gradle.kts deleted file mode 100644 index 2e753f624..000000000 --- a/kmath-core/build.gradle.kts +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - kotlin("multiplatform") -} - - -kotlin { - jvm { - compilations.all { - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs += "-progressive" - } - } - } - js() - - sourceSets { - val commonMain by getting { - dependencies { - api(kotlin("stdlib")) - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) - } - } - val jvmMain by getting { - dependencies { - api(kotlin("stdlib-jdk8")) - } - } - val jvmTest by getting { - dependencies { - implementation(kotlin("test")) - implementation(kotlin("test-junit")) - } - } - val jsMain by getting { - dependencies { - api(kotlin("stdlib-js")) - } - } - val jsTest by getting { - dependencies { - implementation(kotlin("test-js")) - } - } -// mingwMain { -// } -// mingwTest { -// } - } -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt index 3752f6db5..5b65821db 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt @@ -35,9 +35,6 @@ class BufferMatrix( override val shape: IntArray get() = intArrayOf(rowNum, colNum) - override fun suggestFeature(vararg features: MatrixFeature) = - BufferMatrix(rowNum, colNum, buffer, this.features + features) - override fun get(index: IntArray): T = get(index[0], index[1]) override fun get(i: Int, j: Int): T = buffer[i * colNum + j] diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt index 85ddb8786..b2161baf2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/LUPDecomposition.kt @@ -8,19 +8,20 @@ import scientifik.kmath.structures.MutableBufferFactory import scientifik.kmath.structures.NDStructure import scientifik.kmath.structures.get + class LUPDecomposition>( private val elementContext: Ring, internal val lu: NDStructure, val pivot: IntArray, private val even: Boolean -) : LUPDecompositionFeature, DeterminantFeature { +) : DeterminantFeature { /** * Returns the matrix L of the decomposition. * * L is a lower-triangular matrix with [Ring.one] in diagonal */ - override val l: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1], setOf(LFeature)) { i, j -> + val l: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> when { j < i -> lu[i, j] j == i -> elementContext.one @@ -34,7 +35,7 @@ class LUPDecomposition>( * * U is an upper-triangular matrix including the diagonal */ - override val u: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1], setOf(UFeature)) { i, j -> + val u: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> if (j >= i) lu[i, j] else elementContext.zero } @@ -45,7 +46,7 @@ class LUPDecomposition>( * P is a sparse matrix with exactly one element set to [Ring.one] in * each row and each column, all other elements being set to [Ring.zero]. */ - override val p: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> + val p: Matrix = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j -> if (j == pivot[i]) elementContext.one else elementContext.zero } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt index 533e77d61..5b4f3f12d 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/Matrix.kt @@ -107,6 +107,26 @@ interface GenericMatrixContext> : MatrixContext { produce(rowNum, colNum) { i, j -> elementContext.run { get(i, j) * value } } } +/** + * A marker interface representing some matrix feature like diagonal, sparce, zero, etc. Features used to optimize matrix + * operations performance in some cases. + */ +interface MatrixFeature + +object DiagonalFeature : MatrixFeature + +object ZeroFeature : MatrixFeature + +object UnitFeature : MatrixFeature + +interface InverseMatrixFeature : MatrixFeature { + val inverse: Matrix +} + +interface DeterminantFeature : MatrixFeature { + val determinant: T +} + /** * Specialized 2-d structure */ @@ -116,14 +136,6 @@ interface Matrix : NDStructure { val features: Set - /** - * Suggest new feature for this matrix. The result is the new matrix that may or may not reuse existing data structure. - * - * 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): Matrix - operator fun get(i: Int, j: Int): T override fun get(index: IntArray): T = get(index[0], index[1]) @@ -155,22 +167,12 @@ interface Matrix : NDStructure { /** * Build a square matrix from given elements. */ - fun square(vararg elements: T): Matrix { + fun build(vararg elements: T): Matrix { val size: Int = sqrt(elements.size.toDouble()).toInt() if (size * size != elements.size) error("The number of elements ${elements.size} is not a full square") val buffer = elements.asBuffer() return BufferMatrix(size, size, buffer) } - - fun build(rows: Int, columns: Int): MatrixBuilder = MatrixBuilder(rows, columns) - } -} - -class MatrixBuilder(val rows: Int, val columns: Int) { - operator fun invoke(vararg elements: T): Matrix { - if (rows * columns != elements.size) error("The number of elements ${elements.size} is not equal $rows * $columns") - val buffer = elements.asBuffer() - return BufferMatrix(rows, columns, buffer) } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt deleted file mode 100644 index 6b45a14b1..000000000 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/MatrixFeatures.kt +++ /dev/null @@ -1,62 +0,0 @@ -package scientifik.kmath.linear - -/** - * A marker interface representing some matrix feature like diagonal, sparce, zero, etc. Features used to optimize matrix - * operations performance in some cases. - */ -interface MatrixFeature - -/** - * The matrix with this feature is considered to have only diagonal non-null elements - */ -object DiagonalFeature : MatrixFeature - -/** - * Matrix with this feature has all zero elements - */ -object ZeroFeature : MatrixFeature - -/** - * Matrix with this feature have unit elements on diagonal and zero elements in all other places - */ -object UnitFeature : MatrixFeature - -/** - * Inverted matrix feature - */ -interface InverseMatrixFeature : MatrixFeature { - val inverse: Matrix -} - -/** - * A determinant container - */ -interface DeterminantFeature : MatrixFeature { - val determinant: T -} - -@Suppress("FunctionName") -fun DeterminantFeature(determinant: T) = object: DeterminantFeature{ - override val determinant: T = determinant -} - -/** - * Lower triangular matrix - */ -object LFeature: MatrixFeature - -/** - * Upper triangular feature - */ -object UFeature: MatrixFeature - -/** - * TODO add documentation - */ -interface LUPDecompositionFeature : MatrixFeature { - val l: Matrix - val u: Matrix - val p: Matrix -} - -//TODO add sparse matrix feature \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt index 1bab52902..98655ad48 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/VirtualMatrix.kt @@ -8,9 +8,6 @@ class VirtualMatrix( ) : Matrix { override fun get(i: Int, j: Int): T = generator(i, j) - override fun suggestFeature(vararg features: MatrixFeature) = - VirtualMatrix(rowNum, colNum, this.features + features, generator) - override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is Matrix<*>) return false diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/signal/Filter.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/signal/Filter.kt deleted file mode 100644 index 327307985..000000000 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/signal/Filter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package scientifik.kmath.signal - -import scientifik.kmath.structures.NDStructure - - -interface Filter{ - fun process(input : T) : T -} - -interface Convolve{ - fun convolve(input1 : T, input2: T) : T -} - -object Convolve1D - -fun NDStructure.convolve(){ - -} - -abstract class SignalProcessing( - val filter: Filter, - val convolver : Convolve -){ - fun process() -} diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/stat/Stat.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/stat/Stat.kt deleted file mode 100644 index d956f29c2..000000000 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/stat/Stat.kt +++ /dev/null @@ -1,71 +0,0 @@ -package scientifik.kmath.stat - -import scientifik.kmath.operations.Field -import scientifik.kmath.operations.RealField -import scientifik.kmath.operations.Ring -import scientifik.kmath.operations.Space -import scientifik.kmath.structures.NDStructure -import kotlin.math.pow - - - - -// TODO tailrec -fun Ring.pow(element : T, n : Int) : T { - if (n == 0 ){ - return one - } - if (n==1){ - return element - } - val temp = pow(element, n / 2) - return if (n%2==0) temp*temp else element*temp*temp -} - -//fun NDStructure.map(transform : (T) -> R) : NDStructure{ -// -//} - - -/** - * Context for sequence-like operations - */ -class CollectionsOperations(val context: Space){ - fun sum(structure: NDStructure): T { - return with(context){ - var sum = zero - for (element in structure.elements()) { - sum += element.second - } - sum - } - } - -} - -/** - * Context for statistical operations - */ -open class Statistical(val context : Field){ - fun mean(data : NDStructure) = moment(data, 1) - - fun variance(data: NDStructure) = centralMomentum(data, 2) - - fun moment(data: NDStructure, k : Int) : T{ - return with(context){ - var result = zero - val number = data.shape.reduce { acc, i -> acc*i } - for (element in data.elements()){ - result += pow(element.second, k) - } - result/number - } - } - - fun centralMomentum(data: NDStructure, k: Int) = with(context){moment(data, k) - pow(mean(data), k)} - -} - -class RealStatistical : Statistical(RealField){ - fun std(data : NDStructure) = with(context){variance(data).pow(0.5)} -} \ No newline at end of file diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDFactories.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/CreationRoutines.kt similarity index 64% rename from kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDFactories.kt rename to kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/CreationRoutines.kt index 03f716168..51432bc5b 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDFactories.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/CreationRoutines.kt @@ -1,19 +1,14 @@ package scientifik.kmath.structures import scientifik.kmath.operations.RealField.power -import kotlin.math.ceil -import kotlin.math.log -import kotlin.math.min -import kotlin.math.sign +import kotlin.math.* -/** - * Numpy-like factories for [RealNDElement] - */ -object RealNDFactory { + +object RealFactory { /** - * Get a [RealNDElement] filled with [RealNDField.one]. Due to caching all instances with the same shape point to the same object + * Create a NDArray filled with ones */ - fun ones(vararg shape: Int) = NDField.real(shape).one + fun ones(vararg shape: Int) = NDElement.real(shape) { 1.0 } /** * Create a 2D NDArray, with ones on the diagonal and zeros elsewhere. @@ -36,37 +31,40 @@ object RealNDFactory { * Return evenly spaced values within a given interval. * * Values are generated within the half-open interval [start, stop) (in other words, the interval including start but excluding stop). + * @param range use it like: + * (start..stop) to step */ - fun range(range: ClosedFloatingPointRange, step: Double = 1.0) = - NDElement.real1D(ceil((range.endInclusive - range.start) / step).toInt()) { i -> - range.start + i * step - } + fun range(range: Pair, Double>) = + NDElement.real1D(ceil((range.first.endInclusive - range.first.start) / range.second).toInt()) { i -> range.first.start + i * range.second } /** * Return evenly spaced numbers over a specified interval. - * @param range start is starting value, final value depend from endPoint parameter + * @param range use it like: + * (start..stop) to number + * start is starting value, finaly value depend from endPoint parameter * @param endPoint If True, right boundary of range is the last sample. Otherwise, it is not included. */ - fun linspace( - range: ClosedFloatingPointRange, - num: Int = 100, + fun linSpace( + range: Pair, Int>, endPoint: Boolean = true - ): RealNDElement { - val div = if (endPoint) (num - 1) else num - val delta = range.start - range.endInclusive - return if (num > 1) { + ): Pair { + val div = if (endPoint) (range.second - 1) else range.second + val delta = range.first.start - range.first.endInclusive + if (range.second > 1) { val step = delta / div if (step == 0.0) { error("Bad ranges: step = $step") } - NDElement.real1D(num) { - if (endPoint and (it == num - 1)) { - range.endInclusive + val result = NDElement.real1D(range.second) { + if (endPoint and (it == range.second - 1)) { + range.first.endInclusive } - range.start + it * step + range.first.start + it * step } + return result to step } else { - NDElement.real1D(1) { range.start } + val step = Double.NaN + return NDElement.real1D(1) { range.first.start } to step } } @@ -79,25 +77,29 @@ object RealNDFactory { * @param endPoint If True, power(base,stop) is the last sample. Otherwise, it is not included. * @param base - The base of the log space. */ - fun logspace( - range: ClosedFloatingPointRange, - num: Int = 100, + fun logSpace( + range: Pair, Int>, endPoint: Boolean = true, base: Double = 10.0 - ) = linspace(range, num, endPoint).map { power(base, it) } + ): RealNDElement { + val lin = linSpace(range, endPoint).first + val tempFun = { x: Double -> power(base, x) } + return tempFun(lin) // FIXME: RealNDElement.map return not suitable type ( `linSpace(range, endPoint).first.map{power(base, it}`) + } /** * Return numbers spaced evenly on a log scale (a geometric progression). * - * This is similar to [logspace], but with endpoints specified directly. Each output sample is a constant multiple of the previous. + * This is similar to [logSpace], but with endpoints specified directly. Each output sample is a constant multiple of the previous. * @param range use it like: * (start..stop) to number * start is starting value, finaly value depend from endPoint parameter * @param endPoint If True, right boundary of range is the last sample. Otherwise, it is not included. */ - fun geomspace(range: ClosedFloatingPointRange, num : Int = 100, endPoint: Boolean = true): RealNDElement { - var start = range.start - var stop = range.endInclusive + fun geomSpace(range: Pair, Int>, endPoint: Boolean = true): RealNDElement { + var start = range.first.start + var stop = range.first.endInclusive + val num = range.second if (start == 0.0 || stop == 0.0) { error("Geometric sequence cannot include zero") } @@ -108,9 +110,10 @@ object RealNDFactory { outSign = -outSign } - return logspace(log(start, 10.0)..log(stop, 10.0), num, endPoint = endPoint).map { - outSign * it - } + val logRange = logSpace((log(start, 10.0)..log(stop, 10.0) to num), endPoint = endPoint) + val function = { x: Double -> outSign * x } + return function(logRange) // FIXME: `outSign*log_` --- don't define times operator + } /** @@ -123,11 +126,12 @@ object RealNDFactory { error("Input must be 2D NDArray") } val size = min(array.shape[0], array.shape[0]) - return if (offset >= 0) { - NDElement.real1D(size) { i -> array[i, i + offset] } + if (offset >= 0) { + return NDElement.real1D(size) { i -> array[i, i + offset] } } else { - NDElement.real1D(size) { i -> array[i - offset, i] } + return NDElement.real1D(size) { i -> array[i - offset, i] } } + } /** @@ -140,13 +144,13 @@ object RealNDFactory { error("Input must be 1D NDArray") } val size = array.shape[0] - return if (offset < 0) { - NDElement.real2D(size - offset, size) { i, j -> - if (i - offset == j) array[j] else 0.0 + if (offset >= 0) { + return NDElement.real2D(size, size + offset) { i, j -> + if (i == j + offset) array[i] else 0.0 } } else { - NDElement.real2D(size, size + offset) { i, j -> - if (i == j + offset) array[i] else 0.0 + return NDElement.real2D(size - offset, size) { i, j -> + if (i - offset == j) array[j] else 0.0 } } } @@ -162,12 +166,12 @@ object RealNDFactory { error("Input must be 1D NDArray") } val size = if (nCols == 0) array.shape[0] else nCols - return if (increasing) { - NDElement.real2D(array.shape[0], size) { i, j -> + if (increasing) { + return NDElement.real2D(array.shape[0], size) { i, j -> power(array[i], j) } } else { - NDElement.real2D(array.shape[0], size) { i, j -> + return NDElement.real2D(array.shape[0], size) { i, j -> power(array[i], size - j - 1) } } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt index 7ea768c63..097d52723 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDAlgebra.kt @@ -14,7 +14,7 @@ class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : Run /** * The base interface for all nd-algebra implementations * @param T the type of nd-structure element - * @param C the type of the element context + * @param C the type of the context * @param N the type of the structure */ interface NDAlgebra> { @@ -112,13 +112,10 @@ interface NDField, N : NDStructure> : Field, NDRing() - /** - * Create a nd-field for [Double] values or pull it from cache if it was created previously + * Create a nd-field for [Double] values */ - fun real(shape: IntArray) = realNDFieldCache.getOrPut(shape){RealNDField(shape)} + fun real(shape: IntArray) = RealNDField(shape) /** * Create a nd-field with boxing generic buffer diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt index c97f959f3..0fdb53f07 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/NDElement.kt @@ -7,9 +7,6 @@ import scientifik.kmath.operations.Space /** * The root for all [NDStructure] based algebra elements. Does not implement algebra element root because of problems with recursive self-types - * @param T the type of the element of the structure - * @param C the type of the context for the element - * @param N the type of the underlying [NDStructure] */ interface NDElement> : NDStructure { @@ -19,6 +16,9 @@ interface NDElement> : NDStructure { fun N.wrap(): NDElement + fun mapIndexed(transform: C.(index: IntArray, T) -> T) = context.mapIndexed(unwrap(), transform).wrap() + fun map(transform: C.(T) -> T) = context.map(unwrap(), transform).wrap() + companion object { /** * Create a optimized NDArray of doubles @@ -61,17 +61,10 @@ interface NDElement> : NDStructure { } } - -fun > NDElement.mapIndexed(transform: C.(index: IntArray, T) -> T) = - context.mapIndexed(unwrap(), transform).wrap() - -fun > NDElement.map(transform: C.(T) -> T) = context.map(unwrap(), transform).wrap() - - /** * Element by element application of any operation on elements to the whole [NDElement] */ -operator fun > Function1.invoke(ndElement: NDElement) = +operator fun Function1.invoke(ndElement: NDElement) = ndElement.map { value -> this@invoke(value) } /* plus and minus */ @@ -79,13 +72,13 @@ operator fun > Function1.invoke(ndElement: NDElem /** * Summation operation for [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.plus(arg: T) = +operator fun > NDElement.plus(arg: T) = map { value -> arg + value } /** * Subtraction operation between [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.minus(arg: T) = +operator fun > NDElement.minus(arg: T) = map { value -> arg - value } /* prod and div */ @@ -93,13 +86,13 @@ operator fun , N : NDStructure> NDElement.minus(arg: /** * Product operation for [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.times(arg: T) = +operator fun > NDElement.times(arg: T) = map { value -> arg * value } /** * Division operation between [NDElement] and single element */ -operator fun , N : NDStructure> NDElement.div(arg: T) = +operator fun > NDElement.div(arg: T) = map { value -> arg / value } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt index d652bb8a8..bc5832e1c 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealNDField.kt @@ -86,25 +86,11 @@ inline fun BufferedNDField.produceInline(crossinline initiali return BufferedNDFieldElement(this, DoubleBuffer(array)) } -/** - * Map one [RealNDElement] using function with indexes - */ -inline fun RealNDElement.mapIndexed(crossinline transform: RealField.(index: IntArray, Double) -> Double) = - context.produceInline { offset -> transform(strides.index(offset), buffer[offset]) } - -/** - * Map one [RealNDElement] using function without indexes - */ -inline fun RealNDElement.map(crossinline transform: RealField.(Double) -> Double): RealNDElement { - val array = DoubleArray(strides.linearSize) { offset -> RealField.transform(buffer[offset]) } - return BufferedNDFieldElement(context, DoubleBuffer(array)) -} - /** * Element by element application of any operation on elements to the whole array. Just like in numpy */ operator fun Function1.invoke(ndElement: RealNDElement) = - ndElement.map { this@invoke(it) } + ndElement.context.produceInline { i -> invoke(ndElement.buffer[i]) } /* plus and minus */ @@ -113,10 +99,10 @@ operator fun Function1.invoke(ndElement: RealNDElement) = * Summation operation for [BufferedNDElement] and single element */ operator fun RealNDElement.plus(arg: Double) = - map { it + arg } + context.produceInline { i -> buffer[i] + arg } /** * Subtraction operation between [BufferedNDElement] and single element */ operator fun RealNDElement.minus(arg: Double) = - map { it - arg } + context.produceInline { i -> buffer[i] - arg } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt index 09e93483d..5c887f343 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortNDRing.kt @@ -15,7 +15,6 @@ class ShortNDRing(override val shape: IntArray) : override val zero by lazy { produce { ShortRing.zero } } override val one by lazy { produce { ShortRing.one } } - @Suppress("OVERRIDE_BY_INLINE") override inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Short): Buffer = ShortBuffer(ShortArray(size) { initializer(it) }) diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt index 61aa506c4..2a00b84cd 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/MatrixTest.kt @@ -41,14 +41,4 @@ class MatrixTest { assertEquals(5.0, product[1, 0]) assertEquals(6.0, product[2, 2]) } - - @Test - fun testBuilder() { - val matrix = Matrix.build(2, 3)( - 1.0, 0.0, 0.0, - 0.0, 1.0, 2.0 - ) - - assertEquals(2.0, matrix[1, 2]) - } } \ No newline at end of file diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt index bfa720369..ea104355c 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt @@ -13,7 +13,7 @@ class RealLUSolverTest { @Test fun testInvert() { - val matrix = Matrix.square( + val matrix = Matrix.build( 3.0, 1.0, 1.0, 3.0 ) @@ -31,7 +31,7 @@ class RealLUSolverTest { val inverted = LUSolver.real.inverse(decomposed) - val expected = Matrix.square( + val expected = Matrix.build( 0.375, -0.125, -0.125, 0.375 ) diff --git a/kmath-koma/build.gradle.kts b/kmath-koma/build.gradle.kts index b95aaf3c8..20ad02fbe 100644 --- a/kmath-koma/build.gradle.kts +++ b/kmath-koma/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("multiplatform") + id("kotlin-multiplatform") } repositories { @@ -8,12 +8,8 @@ repositories { kotlin { jvm { - compilations.all { - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs += "-progressive" - } - } + compilations["main"].kotlinOptions.jvmTarget = "1.8" + compilations["test"].kotlinOptions.jvmTarget = "1.8" } js() diff --git a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt b/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt index 343d5b8b9..3b7894d18 100644 --- a/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt +++ b/kmath-koma/src/commonMain/kotlin/scientifik.kmath.linear/KomaMatrix.kt @@ -48,25 +48,10 @@ class KomaMatrixContext(val factory: MatrixFactory(val origin: koma.matrix.Matrix, features: Set? = null) : - Matrix { +inline class KomaMatrix(val origin: koma.matrix.Matrix) : Matrix { override val rowNum: Int get() = origin.numRows() override val colNum: Int get() = origin.numCols() - - override val features: Set = features ?: setOf( - object : DeterminantFeature { - override val determinant: T get() = origin.det() - }, - object : LUPDecompositionFeature { - private val lup by lazy { origin.LU() } - override val l: Matrix get() = KomaMatrix(lup.second) - override val u: Matrix get() = KomaMatrix(lup.third) - override val p: Matrix get() = KomaMatrix(lup.first) - } - ) - - override fun suggestFeature(vararg features: MatrixFeature): Matrix = - KomaMatrix(this.origin, this.features + features) + override val features: Set get() = emptySet() override fun get(i: Int, j: Int): T = origin.getGeneric(i, j) } diff --git a/settings.gradle.kts b/settings.gradle.kts index cee985432..a4464d01f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,7 +2,8 @@ pluginManagement { repositories { mavenCentral() maven("https://plugins.gradle.org/m2/") - //maven ("https://dl.bintray.com/kotlin/kotlin-eap") + maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") } + maven { setUrl("https://plugins.gradle.org/m2/") } } }