forked from kscience/kmath
NDArray renamed to NDElement
This commit is contained in:
parent
75bedde1fa
commit
5cd6301f45
@ -1,12 +1,14 @@
|
||||
buildscript {
|
||||
val kotlin_version = "1.3.10"
|
||||
extra["kotlinVersion"] = "1.3.10"
|
||||
|
||||
val kotlinVersion: String by extra
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
|
||||
classpath("org.jfrog.buildinfo:build-info-extractor-gradle:4+")
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ class PhantomBin(val template: BinTemplate, override val value: Number) : Bin<Do
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Immutable histogram with explicit structure for content and additional external bin description.
|
||||
* Bin search is slow, but full histogram algebra is supported.
|
||||
*/
|
||||
class PhantomHistogram(
|
||||
val bins: Map<BinTemplate, IntArray>,
|
||||
val data: NDStructure<Double>
|
||||
|
@ -225,7 +225,7 @@ class ArrayVectorSpace<T : Any>(
|
||||
/**
|
||||
* Member of [ArrayMatrixSpace] which wraps 2-D array
|
||||
*/
|
||||
class ArrayMatrix<T : Any> internal constructor(override val context: ArrayMatrixSpace<T>, val array: NDArray<T>) : Matrix<T> {
|
||||
class ArrayMatrix<T : Any> internal constructor(override val context: ArrayMatrixSpace<T>, val element: NDElement<T>) : Matrix<T> {
|
||||
|
||||
constructor(context: ArrayMatrixSpace<T>, initializer: (Int, Int) -> T) : this(context, context.ndField.produce { list -> initializer(list[0], list[1]) })
|
||||
|
||||
@ -234,32 +234,32 @@ class ArrayMatrix<T : Any> internal constructor(override val context: ArrayMatri
|
||||
override val columns: Int get() = context.columns
|
||||
|
||||
override fun get(i: Int, j: Int): T {
|
||||
return array[i, j]
|
||||
return element[i, j]
|
||||
}
|
||||
|
||||
override val self: ArrayMatrix<T> get() = this
|
||||
}
|
||||
|
||||
|
||||
class ArrayVector<T : Any> internal constructor(override val context: ArrayVectorSpace<T>, val array: NDArray<T>) : Vector<T> {
|
||||
class ArrayVector<T : Any> internal constructor(override val context: ArrayVectorSpace<T>, val element: NDElement<T>) : Vector<T> {
|
||||
|
||||
constructor(context: ArrayVectorSpace<T>, initializer: (Int) -> T) : this(context, context.ndField.produce { list -> initializer(list[0]) })
|
||||
|
||||
init {
|
||||
if (context.size != array.shape[0]) {
|
||||
if (context.size != element.shape[0]) {
|
||||
error("Array dimension mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
override fun get(index: Int): T {
|
||||
return array[index]
|
||||
return element[index]
|
||||
}
|
||||
|
||||
override val self: ArrayVector<T> get() = this
|
||||
|
||||
override fun iterator(): Iterator<T> = (0 until size).map { array[it] }.iterator()
|
||||
override fun iterator(): Iterator<T> = (0 until size).map { element[it] }.iterator()
|
||||
|
||||
override fun copy(): ArrayVector<T> = ArrayVector(context, array)
|
||||
override fun copy(): ArrayVector<T> = ArrayVector(context, element)
|
||||
|
||||
override fun toString(): String = this.joinToString(prefix = "[", postfix = "]", separator = ", ") { it.toString() }
|
||||
}
|
||||
|
@ -1,37 +1,40 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
import scientifik.kmath.operations.*
|
||||
import scientifik.kmath.operations.ExponentialOperations
|
||||
import scientifik.kmath.operations.ExtendedField
|
||||
import scientifik.kmath.operations.PowerOperations
|
||||
import scientifik.kmath.operations.TrigonometricOperations
|
||||
|
||||
|
||||
/**
|
||||
* NDField that supports [ExtendedField] operations on its elements
|
||||
*/
|
||||
class ExtendedNDField<N: Any>(shape: IntArray, override val field: ExtendedField<N>) : NDField<N>(shape, field),
|
||||
TrigonometricOperations<NDArray<N>>,
|
||||
PowerOperations<NDArray<N>>,
|
||||
ExponentialOperations<NDArray<N>> {
|
||||
TrigonometricOperations<NDElement<N>>,
|
||||
PowerOperations<NDElement<N>>,
|
||||
ExponentialOperations<NDElement<N>> {
|
||||
|
||||
override fun produceStructure(initializer: (IntArray) -> N): NDStructure<N> {
|
||||
return genericNdStructure(shape, initializer)
|
||||
}
|
||||
|
||||
override fun power(arg: NDArray<N>, pow: Double): NDArray<N> {
|
||||
override fun power(arg: NDElement<N>, pow: Double): NDElement<N> {
|
||||
return arg.transform { d -> with(field){power(d,pow)} }
|
||||
}
|
||||
|
||||
override fun exp(arg: NDArray<N>): NDArray<N> {
|
||||
override fun exp(arg: NDElement<N>): NDElement<N> {
|
||||
return arg.transform { d -> with(field){exp(d)} }
|
||||
}
|
||||
|
||||
override fun ln(arg: NDArray<N>): NDArray<N> {
|
||||
override fun ln(arg: NDElement<N>): NDElement<N> {
|
||||
return arg.transform { d -> with(field){ln(d)} }
|
||||
}
|
||||
|
||||
override fun sin(arg: NDArray<N>): NDArray<N> {
|
||||
override fun sin(arg: NDElement<N>): NDElement<N> {
|
||||
return arg.transform { d -> with(field){sin(d)} }
|
||||
}
|
||||
|
||||
override fun cos(arg: NDArray<N>): NDArray<N> {
|
||||
override fun cos(arg: NDElement<N>): NDElement<N> {
|
||||
return arg.transform { d -> with(field){cos(d)} }
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class ShapeMismatchException(val expected: IntArray, val actual: IntArray) : Run
|
||||
* @param field - operations field defined on individual array element
|
||||
* @param T the type of the element contained in NDArray
|
||||
*/
|
||||
abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field<NDArray<T>> {
|
||||
abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field<NDElement<T>> {
|
||||
|
||||
abstract fun produceStructure(initializer: (IntArray) -> T): NDStructure<T>
|
||||
|
||||
@ -23,17 +23,17 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
* Create new instance of NDArray using field shape and given initializer
|
||||
* The producer takes list of indices as argument and returns contained value
|
||||
*/
|
||||
fun produce(initializer: (IntArray) -> T): NDArray<T> = NDArray(this, produceStructure(initializer))
|
||||
fun produce(initializer: (IntArray) -> T): NDElement<T> = NDElement(this, produceStructure(initializer))
|
||||
|
||||
override val zero: NDArray<T> by lazy {
|
||||
override val zero: NDElement<T> by lazy {
|
||||
produce { this.field.zero }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the shape of given NDArray and throw exception if it does not coincide with shape of the field
|
||||
*/
|
||||
private fun checkShape(vararg arrays: NDArray<T>) {
|
||||
arrays.forEach {
|
||||
private fun checkShape(vararg elements: NDElement<T>) {
|
||||
elements.forEach {
|
||||
if (!shape.contentEquals(it.shape)) {
|
||||
throw ShapeMismatchException(shape, it.shape)
|
||||
}
|
||||
@ -43,7 +43,7 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
/**
|
||||
* Element-by-element addition
|
||||
*/
|
||||
override fun add(a: NDArray<T>, b: NDArray<T>): NDArray<T> {
|
||||
override fun add(a: NDElement<T>, b: NDElement<T>): NDElement<T> {
|
||||
checkShape(a, b)
|
||||
return produce { with(field) { a[it] + b[it] } }
|
||||
}
|
||||
@ -51,18 +51,18 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
/**
|
||||
* Multiply all elements by cinstant
|
||||
*/
|
||||
override fun multiply(a: NDArray<T>, k: Double): NDArray<T> {
|
||||
override fun multiply(a: NDElement<T>, k: Double): NDElement<T> {
|
||||
checkShape(a)
|
||||
return produce { with(field) { a[it] * k } }
|
||||
}
|
||||
|
||||
override val one: NDArray<T>
|
||||
override val one: NDElement<T>
|
||||
get() = produce { this.field.one }
|
||||
|
||||
/**
|
||||
* Element-by-element multiplication
|
||||
*/
|
||||
override fun multiply(a: NDArray<T>, b: NDArray<T>): NDArray<T> {
|
||||
override fun multiply(a: NDElement<T>, b: NDElement<T>): NDElement<T> {
|
||||
checkShape(a)
|
||||
return produce { with(field) { a[it] * b[it] } }
|
||||
}
|
||||
@ -70,7 +70,7 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
/**
|
||||
* Element-by-element division
|
||||
*/
|
||||
override fun divide(a: NDArray<T>, b: NDArray<T>): NDArray<T> {
|
||||
override fun divide(a: NDElement<T>, b: NDElement<T>): NDElement<T> {
|
||||
checkShape(a)
|
||||
return produce { with(field) { a[it] / b[it] } }
|
||||
}
|
||||
@ -78,12 +78,12 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
/**
|
||||
* Reverse sum operation
|
||||
*/
|
||||
operator fun <T> T.plus(arg: NDArray<T>): NDArray<T> = arg + this
|
||||
operator fun <T> T.plus(arg: NDElement<T>): NDElement<T> = arg + this
|
||||
|
||||
/**
|
||||
* Reverse minus operation
|
||||
*/
|
||||
operator fun <T> T.minus(arg: NDArray<T>): NDArray<T> = arg.transform { _, value ->
|
||||
operator fun <T> T.minus(arg: NDElement<T>): NDElement<T> = arg.transform { _, value ->
|
||||
with(arg.context.field) {
|
||||
this@minus - value
|
||||
}
|
||||
@ -92,12 +92,12 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
/**
|
||||
* Reverse product operation
|
||||
*/
|
||||
operator fun <T> T.times(arg: NDArray<T>): NDArray<T> = arg * this
|
||||
operator fun <T> T.times(arg: NDElement<T>): NDElement<T> = arg * this
|
||||
|
||||
/**
|
||||
* Reverse division operation
|
||||
*/
|
||||
operator fun <T> T.div(arg: NDArray<T>): NDArray<T> = arg.transform { _, value ->
|
||||
operator fun <T> T.div(arg: NDElement<T>): NDElement<T> = arg.transform { _, value ->
|
||||
with(arg.context.field) {
|
||||
this@div / value
|
||||
}
|
||||
@ -107,37 +107,37 @@ abstract class NDField<T>(val shape: IntArray, open val field: Field<T>) : Field
|
||||
/**
|
||||
* Immutable [NDStructure] coupled to the context. Emulates Python ndarray
|
||||
*/
|
||||
class NDArray<T>(override val context: NDField<T>, private val structure: NDStructure<T>) : FieldElement<NDArray<T>, NDField<T>>, NDStructure<T> by structure {
|
||||
class NDElement<T>(override val context: NDField<T>, private val structure: NDStructure<T>) : FieldElement<NDElement<T>, NDField<T>>, NDStructure<T> by structure {
|
||||
|
||||
//TODO ensure structure is immutable
|
||||
|
||||
override val self: NDArray<T>
|
||||
override val self: NDElement<T>
|
||||
get() = this
|
||||
|
||||
inline fun transform(crossinline action: (IntArray, T) -> T): NDArray<T> = context.produce { action(it, get(*it)) }
|
||||
inline fun transform(crossinline action: (T) -> T): NDArray<T> = context.produce { action(get(*it)) }
|
||||
inline fun transform(crossinline action: (IntArray, T) -> T): NDElement<T> = context.produce { action(it, get(*it)) }
|
||||
inline fun transform(crossinline action: (T) -> T): NDElement<T> = context.produce { action(get(*it)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Element by element application of any operation on elements to the whole array. Just like in numpy
|
||||
*/
|
||||
operator fun <T> Function1<T, T>.invoke(ndArray: NDArray<T>): NDArray<T> = ndArray.transform { _, value -> this(value) }
|
||||
operator fun <T> Function1<T, T>.invoke(ndElement: NDElement<T>): NDElement<T> = ndElement.transform { _, value -> this(value) }
|
||||
|
||||
/* plus and minus */
|
||||
|
||||
/**
|
||||
* Summation operation for [NDArray] and single element
|
||||
* Summation operation for [NDElement] and single element
|
||||
*/
|
||||
operator fun <T> NDArray<T>.plus(arg: T): NDArray<T> = transform { _, value ->
|
||||
operator fun <T> NDElement<T>.plus(arg: T): NDElement<T> = transform { _, value ->
|
||||
with(context.field) {
|
||||
arg + value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtraction operation between [NDArray] and single element
|
||||
* Subtraction operation between [NDElement] and single element
|
||||
*/
|
||||
operator fun <T> NDArray<T>.minus(arg: T): NDArray<T> = transform { _, value ->
|
||||
operator fun <T> NDElement<T>.minus(arg: T): NDElement<T> = transform { _, value ->
|
||||
with(context.field) {
|
||||
arg - value
|
||||
}
|
||||
@ -146,18 +146,18 @@ operator fun <T> NDArray<T>.minus(arg: T): NDArray<T> = transform { _, value ->
|
||||
/* prod and div */
|
||||
|
||||
/**
|
||||
* Product operation for [NDArray] and single element
|
||||
* Product operation for [NDElement] and single element
|
||||
*/
|
||||
operator fun <T> NDArray<T>.times(arg: T): NDArray<T> = transform { _, value ->
|
||||
operator fun <T> NDElement<T>.times(arg: T): NDElement<T> = transform { _, value ->
|
||||
with(context.field) {
|
||||
arg * value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Division operation between [NDArray] and single element
|
||||
* Division operation between [NDElement] and single element
|
||||
*/
|
||||
operator fun <T> NDArray<T>.div(arg: T): NDArray<T> = transform { _, value ->
|
||||
operator fun <T> NDElement<T>.div(arg: T): NDElement<T> = transform { _, value ->
|
||||
with(context.field) {
|
||||
arg / value
|
||||
}
|
||||
@ -173,23 +173,23 @@ object NDArrays {
|
||||
/**
|
||||
* Create a platform-optimized NDArray of doubles
|
||||
*/
|
||||
fun realNDArray(shape: IntArray, initializer: (IntArray) -> Double = { 0.0 }): NDArray<Double> {
|
||||
fun realNDArray(shape: IntArray, initializer: (IntArray) -> Double = { 0.0 }): NDElement<Double> {
|
||||
return ExtendedNDField(shape, DoubleField).produce(initializer)
|
||||
}
|
||||
|
||||
fun real1DArray(dim: Int, initializer: (Int) -> Double = { _ -> 0.0 }): NDArray<Double> {
|
||||
fun real1DArray(dim: Int, initializer: (Int) -> Double = { _ -> 0.0 }): NDElement<Double> {
|
||||
return realNDArray(intArrayOf(dim)) { initializer(it[0]) }
|
||||
}
|
||||
|
||||
fun real2DArray(dim1: Int, dim2: Int, initializer: (Int, Int) -> Double = { _, _ -> 0.0 }): NDArray<Double> {
|
||||
fun real2DArray(dim1: Int, dim2: Int, initializer: (Int, Int) -> Double = { _, _ -> 0.0 }): NDElement<Double> {
|
||||
return realNDArray(intArrayOf(dim1, dim2)) { initializer(it[0], it[1]) }
|
||||
}
|
||||
|
||||
fun real3DArray(dim1: Int, dim2: Int, dim3: Int, initializer: (Int, Int, Int) -> Double = { _, _, _ -> 0.0 }): NDArray<Double> {
|
||||
fun real3DArray(dim1: Int, dim2: Int, dim3: Int, initializer: (Int, Int, Int) -> Double = { _, _, _ -> 0.0 }): NDElement<Double> {
|
||||
return realNDArray(intArrayOf(dim1, dim2, dim3)) { initializer(it[0], it[1], it[2]) }
|
||||
}
|
||||
|
||||
inline fun produceReal(shape: IntArray, block: ExtendedNDField<Double>.() -> NDArray<Double>) = ExtendedNDField(shape, DoubleField).run(block)
|
||||
inline fun produceReal(shape: IntArray, block: ExtendedNDField<Double>.() -> NDElement<Double>) = ExtendedNDField(shape, DoubleField).run(block)
|
||||
|
||||
// /**
|
||||
// * Simple boxing NDField
|
||||
@ -199,7 +199,7 @@ object NDArrays {
|
||||
/**
|
||||
* Simple boxing NDArray
|
||||
*/
|
||||
fun <T : Any> create(field: Field<T>, shape: IntArray, initializer: (IntArray) -> T): NDArray<T> {
|
||||
fun <T : Any> create(field: Field<T>, shape: IntArray, initializer: (IntArray) -> T): NDElement<T> {
|
||||
return GenericNDField(shape, field).produce { initializer(it) }
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package scientifik.kmath.structures
|
||||
|
||||
import scientifik.kmath.linear.Vector
|
||||
import scientifik.kmath.linear.VectorL2Norm
|
||||
import scientifik.kmath.operations.Norm
|
||||
import scientifik.kmath.structures.NDArrays.produceReal
|
||||
import scientifik.kmath.structures.NDArrays.real2DArray
|
||||
@ -53,8 +51,8 @@ class NumberNDFieldTest {
|
||||
assertEquals(2.0, result[0,2])
|
||||
}
|
||||
|
||||
object L2Norm: Norm<NDArray<out Number>, Double> {
|
||||
override fun norm(arg: NDArray<out Number>): Double {
|
||||
object L2Norm: Norm<NDElement<out Number>, Double> {
|
||||
override fun norm(arg: NDElement<out Number>): Double {
|
||||
return kotlin.math.sqrt(arg.sumByDouble { it.second.toDouble() })
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user