v0.2.0 #206
@ -31,38 +31,35 @@ class DotBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun commonsMathMultiplication() {
|
fun cmDot() {
|
||||||
CMMatrixContext {
|
CMMatrixContext {
|
||||||
cmMatrix1 dot cmMatrix2
|
cmMatrix1 dot cmMatrix2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlMultiplication() {
|
fun ejmlDot() {
|
||||||
EjmlMatrixContext {
|
EjmlMatrixContext {
|
||||||
ejmlMatrix1 dot ejmlMatrix2
|
ejmlMatrix1 dot ejmlMatrix2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlMultiplicationwithConversion() {
|
fun ejmlDotWithConversion() {
|
||||||
EjmlMatrixContext {
|
EjmlMatrixContext {
|
||||||
val ejmlMatrix1 = matrix1.toEjml()
|
matrix1 dot matrix2
|
||||||
val ejmlMatrix2 = matrix2.toEjml()
|
|
||||||
|
|
||||||
ejmlMatrix1 dot ejmlMatrix2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun bufferedMultiplication() {
|
fun bufferedDot() {
|
||||||
BufferMatrixContext(RealField, Buffer.Companion::real).invoke {
|
BufferMatrixContext(RealField, Buffer.Companion::real).invoke {
|
||||||
matrix1 dot matrix2
|
matrix1 dot matrix2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun realMultiplication() {
|
fun realDot() {
|
||||||
RealMatrixContext {
|
RealMatrixContext {
|
||||||
matrix1 dot matrix2
|
matrix1 dot matrix2
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,9 @@ class LinearAlgebraBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmathLUPInversion() {
|
fun kmathLUPInversion() {
|
||||||
MatrixContext.real.inverseWithLUP(matrix)
|
MatrixContext.real{
|
||||||
|
inverseWithLUP(matrix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
|
@ -23,7 +23,7 @@ internal class ViktorBenchmark {
|
|||||||
fun automaticFieldAddition() {
|
fun automaticFieldAddition() {
|
||||||
autoField {
|
autoField {
|
||||||
var res: NDStructure<Double> = one
|
var res: NDStructure<Double> = one
|
||||||
repeat(n) { res += one }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ internal class ViktorBenchmark {
|
|||||||
fun realFieldAddition() {
|
fun realFieldAddition() {
|
||||||
realField {
|
realField {
|
||||||
var res: NDStructure<Double> = one
|
var res: NDStructure<Double> = one
|
||||||
repeat(n) { res += one }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ internal class ViktorBenchmark {
|
|||||||
fun viktorFieldAddition() {
|
fun viktorFieldAddition() {
|
||||||
viktorField {
|
viktorField {
|
||||||
var res = one
|
var res = one
|
||||||
repeat(n) { res += one }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ internal class ViktorLogBenchmark {
|
|||||||
final val n: Int = 100
|
final val n: Int = 100
|
||||||
|
|
||||||
// automatically build context most suited for given type.
|
// automatically build context most suited for given type.
|
||||||
final val autoField: BufferedNDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
|
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
|
||||||
final val realField: RealNDField = NDAlgebra.real(dim, dim)
|
final val realField: RealNDField = NDAlgebra.real(dim, dim)
|
||||||
final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim))
|
final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim))
|
||||||
|
|
||||||
@ -29,6 +29,15 @@ internal class ViktorLogBenchmark {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun viktorFieldLog() {
|
||||||
|
viktorField {
|
||||||
|
val fortyTwo = produce { 42.0 }
|
||||||
|
var res = one
|
||||||
|
repeat(n) { res = ln(fortyTwo) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun rawViktorLog() {
|
fun rawViktorLog() {
|
||||||
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
|
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
|
||||||
|
@ -48,22 +48,20 @@ class StreamRealNDField(
|
|||||||
return NDBuffer(strides, array.asBuffer())
|
return NDBuffer(strides, array.asBuffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun map(
|
override fun NDStructure<Double>.map(
|
||||||
arg: NDStructure<Double>,
|
|
||||||
transform: RealField.(Double) -> Double,
|
transform: RealField.(Double) -> Double,
|
||||||
): NDBuffer<Double> {
|
): NDBuffer<Double> {
|
||||||
val array = Arrays.stream(arg.buffer.array).parallel().map { RealField.transform(it) }.toArray()
|
val array = Arrays.stream(buffer.array).parallel().map { RealField.transform(it) }.toArray()
|
||||||
return NDBuffer(strides, array.asBuffer())
|
return NDBuffer(strides, array.asBuffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mapIndexed(
|
override fun NDStructure<Double>.mapIndexed(
|
||||||
arg: NDStructure<Double>,
|
|
||||||
transform: RealField.(index: IntArray, Double) -> Double,
|
transform: RealField.(index: IntArray, Double) -> Double,
|
||||||
): NDBuffer<Double> {
|
): NDBuffer<Double> {
|
||||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||||
RealField.transform(
|
RealField.transform(
|
||||||
strides.index(offset),
|
strides.index(offset),
|
||||||
arg.buffer.array[offset]
|
buffer.array[offset]
|
||||||
)
|
)
|
||||||
}.toArray()
|
}.toArray()
|
||||||
|
|
||||||
@ -81,25 +79,25 @@ class StreamRealNDField(
|
|||||||
return NDBuffer(strides, array.asBuffer())
|
return NDBuffer(strides, array.asBuffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = map(arg) { power(it, pow) }
|
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map() { power(it, pow) }
|
||||||
|
|
||||||
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { exp(it) }
|
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { exp(it) }
|
||||||
|
|
||||||
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { ln(it) }
|
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { ln(it) }
|
||||||
|
|
||||||
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { sin(it) }
|
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sin(it) }
|
||||||
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { cos(it) }
|
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cos(it) }
|
||||||
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { tan(it) }
|
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tan(it) }
|
||||||
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { asin(it) }
|
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asin(it) }
|
||||||
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { acos(it) }
|
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acos(it) }
|
||||||
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { atan(it) }
|
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atan(it) }
|
||||||
|
|
||||||
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { sinh(it) }
|
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sinh(it) }
|
||||||
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { cosh(it) }
|
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cosh(it) }
|
||||||
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { tanh(it) }
|
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tanh(it) }
|
||||||
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { asinh(it) }
|
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asinh(it) }
|
||||||
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { acosh(it) }
|
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acosh(it) }
|
||||||
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { atanh(it) }
|
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)
|
fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)
|
@ -3,6 +3,7 @@ package kscience.kmath.linear
|
|||||||
import kscience.kmath.nd.NDStructure
|
import kscience.kmath.nd.NDStructure
|
||||||
import kscience.kmath.nd.Structure2D
|
import kscience.kmath.nd.Structure2D
|
||||||
import kscience.kmath.operations.Ring
|
import kscience.kmath.operations.Ring
|
||||||
|
import kscience.kmath.operations.invoke
|
||||||
import kscience.kmath.structures.Buffer
|
import kscience.kmath.structures.Buffer
|
||||||
import kscience.kmath.structures.BufferFactory
|
import kscience.kmath.structures.BufferFactory
|
||||||
import kscience.kmath.structures.asSequence
|
import kscience.kmath.structures.asSequence
|
||||||
@ -28,6 +29,62 @@ public class BufferMatrixContext<T : Any, R : Ring<T>>(
|
|||||||
|
|
||||||
public 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)
|
||||||
|
|
||||||
|
private fun Matrix<T>.toBufferMatrix(): BufferMatrix<T> = if (this is BufferMatrix) this else {
|
||||||
|
produce(rowNum, colNum) { i, j -> get(i, j) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun one(rows: Int, columns: Int): Matrix<Double> = VirtualMatrix(rows, columns) { i, j ->
|
||||||
|
if (i == j) 1.0 else 0.0
|
||||||
|
} + DiagonalFeature
|
||||||
|
|
||||||
|
public override infix fun Matrix<T>.dot(other: Matrix<T>): BufferMatrix<T> {
|
||||||
|
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
||||||
|
val bufferMatrix = toBufferMatrix()
|
||||||
|
val otherBufferMatrix = other.toBufferMatrix()
|
||||||
|
return elementContext {
|
||||||
|
produce(rowNum, other.colNum) { i, j ->
|
||||||
|
var res = one
|
||||||
|
for (l in 0 until colNum) {
|
||||||
|
res += bufferMatrix[i, l] * otherBufferMatrix[l, j]
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override infix fun Matrix<T>.dot(vector: Point<T>): Point<T> {
|
||||||
|
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
||||||
|
val bufferMatrix = toBufferMatrix()
|
||||||
|
return elementContext {
|
||||||
|
bufferFactory(rowNum) { i ->
|
||||||
|
var res = one
|
||||||
|
for (j in 0 until colNum) {
|
||||||
|
res += bufferMatrix[i, j] * vector[j]
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun add(a: Matrix<T>, b: Matrix<T>): BufferMatrix<T> {
|
||||||
|
require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" }
|
||||||
|
require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" }
|
||||||
|
val aBufferMatrix = a.toBufferMatrix()
|
||||||
|
val bBufferMatrix = b.toBufferMatrix()
|
||||||
|
return elementContext {
|
||||||
|
produce(a.rowNum, a.colNum) { i, j ->
|
||||||
|
aBufferMatrix[i, j] + bBufferMatrix[i, j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun multiply(a: Matrix<T>, k: Number): BufferMatrix<T> {
|
||||||
|
val aBufferMatrix = a.toBufferMatrix()
|
||||||
|
return elementContext {
|
||||||
|
produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,12 +60,6 @@ public operator fun <T : Any> Matrix<T>.plus(newFeatures: Collection<MatrixFeatu
|
|||||||
MatrixWrapper(this, newFeatures.toSet())
|
MatrixWrapper(this, newFeatures.toSet())
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun Structure2D.Companion.real(
|
|
||||||
rows: Int,
|
|
||||||
columns: Int,
|
|
||||||
initializer: (Int, Int) -> Double,
|
|
||||||
): BufferMatrix<Double> = MatrixContext.real.produce(rows, columns, initializer)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a square matrix from given elements.
|
* Build a square matrix from given elements.
|
||||||
*/
|
*/
|
||||||
|
@ -2,10 +2,9 @@ package kscience.kmath.linear
|
|||||||
|
|
||||||
import kscience.kmath.structures.RealBuffer
|
import kscience.kmath.structures.RealBuffer
|
||||||
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE")
|
|
||||||
public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
||||||
|
|
||||||
public override inline fun produce(
|
public override fun produce(
|
||||||
rows: Int,
|
rows: Int,
|
||||||
columns: Int,
|
columns: Int,
|
||||||
initializer: (i: Int, j: Int) -> Double,
|
initializer: (i: Int, j: Int) -> Double,
|
||||||
@ -14,7 +13,7 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
|||||||
return BufferMatrix(rows, columns, buffer)
|
return BufferMatrix(rows, columns, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Matrix<Double>.wrap(): BufferMatrix<Double> = if (this is BufferMatrix) this else {
|
public fun Matrix<Double>.toBufferMatrix(): BufferMatrix<Double> = if (this is BufferMatrix) this else {
|
||||||
produce(rowNum, colNum) { i, j -> get(i, j) }
|
produce(rowNum, colNum) { i, j -> get(i, j) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,10 +23,12 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
|||||||
|
|
||||||
public override infix fun Matrix<Double>.dot(other: Matrix<Double>): BufferMatrix<Double> {
|
public override infix fun Matrix<Double>.dot(other: Matrix<Double>): BufferMatrix<Double> {
|
||||||
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
require(colNum == other.rowNum) { "Matrix dot operation dimension mismatch: ($rowNum, $colNum) x (${other.rowNum}, ${other.colNum})" }
|
||||||
|
val bufferMatrix = toBufferMatrix()
|
||||||
|
val otherBufferMatrix = other.toBufferMatrix()
|
||||||
return produce(rowNum, other.colNum) { i, j ->
|
return produce(rowNum, other.colNum) { i, j ->
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
for (l in 0 until colNum) {
|
for (l in 0 until colNum) {
|
||||||
res += get(i, l) * other.get(l, j)
|
res += bufferMatrix[i, l] * otherBufferMatrix[l, j]
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -35,10 +36,11 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
|||||||
|
|
||||||
public override infix fun Matrix<Double>.dot(vector: Point<Double>): Point<Double> {
|
public override infix fun Matrix<Double>.dot(vector: Point<Double>): Point<Double> {
|
||||||
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
require(colNum == vector.size) { "Matrix dot vector operation dimension mismatch: ($rowNum, $colNum) x (${vector.size})" }
|
||||||
|
val bufferMatrix = toBufferMatrix()
|
||||||
return RealBuffer(rowNum) { i ->
|
return RealBuffer(rowNum) { i ->
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
for (j in 0 until colNum) {
|
for (j in 0 until colNum) {
|
||||||
res += get(i, j) * vector[j]
|
res += bufferMatrix[i, j] * vector[j]
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -47,17 +49,23 @@ public object RealMatrixContext : MatrixContext<Double, BufferMatrix<Double>> {
|
|||||||
override fun add(a: Matrix<Double>, b: Matrix<Double>): BufferMatrix<Double> {
|
override fun add(a: Matrix<Double>, b: Matrix<Double>): BufferMatrix<Double> {
|
||||||
require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" }
|
require(a.rowNum == b.rowNum) { "Row number mismatch in matrix addition. Left side: ${a.rowNum}, right side: ${b.rowNum}" }
|
||||||
require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" }
|
require(a.colNum == b.colNum) { "Column number mismatch in matrix addition. Left side: ${a.colNum}, right side: ${b.colNum}" }
|
||||||
|
val aBufferMatrix = a.toBufferMatrix()
|
||||||
|
val bBufferMatrix = b.toBufferMatrix()
|
||||||
return produce(a.rowNum, a.colNum) { i, j ->
|
return produce(a.rowNum, a.colNum) { i, j ->
|
||||||
a[i, j] + b[i, j]
|
aBufferMatrix[i, j] + bBufferMatrix[i, j]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Matrix<Double>.times(value: Double): BufferMatrix<Double> =
|
override fun Matrix<Double>.times(value: Double): BufferMatrix<Double> {
|
||||||
produce(rowNum, colNum) { i, j -> get(i, j) * value }
|
val bufferMatrix = toBufferMatrix()
|
||||||
|
return produce(rowNum, colNum) { i, j -> bufferMatrix[i, j] * value }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> =
|
override fun multiply(a: Matrix<Double>, k: Number): BufferMatrix<Double> {
|
||||||
produce(a.rowNum, a.colNum) { i, j -> a[i, j] * k.toDouble() }
|
val aBufferMatrix = a.toBufferMatrix()
|
||||||
|
return produce(a.rowNum, a.colNum) { i, j -> aBufferMatrix[i, j] * k.toDouble() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,24 +28,24 @@ public interface BufferNDAlgebra<T, C> : NDAlgebra<T, C> {
|
|||||||
else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) }
|
else -> bufferFactory(strides.linearSize) { offset -> get(strides.index(offset)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun map(arg: NDStructure<T>, transform: C.(T) -> T): NDBuffer<T> {
|
override fun NDStructure<T>.map(transform: C.(T) -> T): NDBuffer<T> {
|
||||||
val buffer = bufferFactory(strides.linearSize) { offset ->
|
val buffer = bufferFactory(strides.linearSize) { offset ->
|
||||||
elementContext.transform(arg.buffer[offset])
|
elementContext.transform(buffer[offset])
|
||||||
}
|
}
|
||||||
return NDBuffer(strides, buffer)
|
return NDBuffer(strides, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mapIndexed(arg: NDStructure<T>, transform: C.(index: IntArray, T) -> T): NDStructure<T> {
|
override fun NDStructure<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDBuffer<T> {
|
||||||
val buffer = bufferFactory(strides.linearSize) { offset ->
|
val buffer = bufferFactory(strides.linearSize) { offset ->
|
||||||
elementContext.transform(
|
elementContext.transform(
|
||||||
strides.index(offset),
|
strides.index(offset),
|
||||||
arg.buffer[offset]
|
buffer[offset]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return NDBuffer(strides, buffer)
|
return NDBuffer(strides, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: C.(T, T) -> T): NDStructure<T> {
|
override fun combine(a: NDStructure<T>, b: NDStructure<T>, transform: C.(T, T) -> T): NDBuffer<T> {
|
||||||
val buffer = bufferFactory(strides.linearSize) { offset ->
|
val buffer = bufferFactory(strides.linearSize) { offset ->
|
||||||
elementContext.transform(a.buffer[offset], b.buffer[offset])
|
elementContext.transform(a.buffer[offset], b.buffer[offset])
|
||||||
}
|
}
|
||||||
|
@ -70,25 +70,25 @@ public class ComplexNDField(
|
|||||||
// return BufferedNDFieldElement(this, buffer)
|
// return BufferedNDFieldElement(this, buffer)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
override fun power(arg: NDStructure<Complex>, pow: Number): NDBuffer<Complex> = map(arg) { power(it, pow) }
|
override fun power(arg: NDStructure<Complex>, pow: Number): NDBuffer<Complex> = arg.map() { power(it, pow) }
|
||||||
|
|
||||||
override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { exp(it) }
|
override fun exp(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { exp(it) }
|
||||||
|
|
||||||
override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { ln(it) }
|
override fun ln(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { ln(it) }
|
||||||
|
|
||||||
override fun sin(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { sin(it) }
|
override fun sin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { sin(it) }
|
||||||
override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { cos(it) }
|
override fun cos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cos(it) }
|
||||||
override fun tan(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { tan(it) }
|
override fun tan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { tan(it) }
|
||||||
override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { asin(it) }
|
override fun asin(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asin(it) }
|
||||||
override fun acos(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { acos(it) }
|
override fun acos(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { acos(it) }
|
||||||
override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { atan(it) }
|
override fun atan(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atan(it) }
|
||||||
|
|
||||||
override fun sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { sinh(it) }
|
override fun sinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { sinh(it) }
|
||||||
override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { cosh(it) }
|
override fun cosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { cosh(it) }
|
||||||
override fun tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { tanh(it) }
|
override fun tanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { tanh(it) }
|
||||||
override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { asinh(it) }
|
override fun asinh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { asinh(it) }
|
||||||
override fun acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { acosh(it) }
|
override fun acosh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { acosh(it) }
|
||||||
override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = map(arg) { atanh(it) }
|
override fun atanh(arg: NDStructure<Complex>): NDBuffer<Complex> = arg.map() { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,12 +40,12 @@ public interface NDAlgebra<T, C> {
|
|||||||
/**
|
/**
|
||||||
* Maps elements from one structure to another one by applying [transform] to them.
|
* Maps elements from one structure to another one by applying [transform] to them.
|
||||||
*/
|
*/
|
||||||
public fun map(arg: NDStructure<T>, transform: C.(T) -> T): NDStructure<T>
|
public fun NDStructure<T>.map(transform: C.(T) -> T): NDStructure<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps elements from one structure to another one by applying [transform] to them alongside with their indices.
|
* Maps elements from one structure to another one by applying [transform] to them alongside with their indices.
|
||||||
*/
|
*/
|
||||||
public fun mapIndexed(arg: NDStructure<T>, transform: C.(index: IntArray, T) -> T): NDStructure<T>
|
public fun NDStructure<T>.mapIndexed(transform: C.(index: IntArray, T) -> T): NDStructure<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines two structures into one.
|
* Combines two structures into one.
|
||||||
@ -56,7 +56,7 @@ public interface NDAlgebra<T, C> {
|
|||||||
* Element-wise invocation of function working on [T] on a [NDStructure].
|
* Element-wise invocation of function working on [T] on a [NDStructure].
|
||||||
*/
|
*/
|
||||||
public operator fun Function1<T, T>.invoke(structure: NDStructure<T>): NDStructure<T> =
|
public operator fun Function1<T, T>.invoke(structure: NDStructure<T>): NDStructure<T> =
|
||||||
map(structure) { value -> this@invoke(value) }
|
structure.map() { value -> this@invoke(value) }
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
|||||||
* @param k the multiplier.
|
* @param k the multiplier.
|
||||||
* @return the product.
|
* @return the product.
|
||||||
*/
|
*/
|
||||||
public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = map(a) { multiply(it, k) }
|
public override fun multiply(a: NDStructure<T>, k: Number): NDStructure<T> = a.map() { multiply(it, k) }
|
||||||
|
|
||||||
// TODO move to extensions after KEEP-176
|
// TODO move to extensions after KEEP-176
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
|||||||
* @param arg the augend.
|
* @param arg the augend.
|
||||||
* @return the sum.
|
* @return the sum.
|
||||||
*/
|
*/
|
||||||
public operator fun NDStructure<T>.plus(arg: T): NDStructure<T> = map(this) { value -> add(arg, value) }
|
public operator fun NDStructure<T>.plus(arg: T): NDStructure<T> = this.map() { value -> add(arg, value) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtracts an element from ND structure of it.
|
* Subtracts an element from ND structure of it.
|
||||||
@ -129,7 +129,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
|||||||
* @param arg the divisor.
|
* @param arg the divisor.
|
||||||
* @return the quotient.
|
* @return the quotient.
|
||||||
*/
|
*/
|
||||||
public operator fun NDStructure<T>.minus(arg: T): NDStructure<T> = map(this) { value -> add(arg, -value) }
|
public operator fun NDStructure<T>.minus(arg: T): NDStructure<T> = this.map() { value -> add(arg, -value) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an element to ND structure of it.
|
* Adds an element to ND structure of it.
|
||||||
@ -138,7 +138,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
|||||||
* @param arg the augend.
|
* @param arg the augend.
|
||||||
* @return the sum.
|
* @return the sum.
|
||||||
*/
|
*/
|
||||||
public operator fun T.plus(arg: NDStructure<T>): NDStructure<T> = map(arg) { value -> add(this@plus, value) }
|
public operator fun T.plus(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> add(this@plus, value) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtracts an ND structure from an element of it.
|
* Subtracts an ND structure from an element of it.
|
||||||
@ -147,7 +147,7 @@ public interface NDSpace<T, S : Space<T>> : Space<NDStructure<T>>, NDAlgebra<T,
|
|||||||
* @param arg the divisor.
|
* @param arg the divisor.
|
||||||
* @return the quotient.
|
* @return the quotient.
|
||||||
*/
|
*/
|
||||||
public operator fun T.minus(arg: NDStructure<T>): NDStructure<T> = map(arg) { value -> add(-this@minus, value) }
|
public operator fun T.minus(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> add(-this@minus, value) }
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
|
|||||||
* @param arg the multiplier.
|
* @param arg the multiplier.
|
||||||
* @return the product.
|
* @return the product.
|
||||||
*/
|
*/
|
||||||
public operator fun NDStructure<T>.times(arg: T): NDStructure<T> = map(this) { value -> multiply(arg, value) }
|
public operator fun NDStructure<T>.times(arg: T): NDStructure<T> = this.map() { value -> multiply(arg, value) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplies an element by a ND structure of it.
|
* Multiplies an element by a ND structure of it.
|
||||||
@ -188,7 +188,7 @@ public interface NDRing<T, R : Ring<T>> : Ring<NDStructure<T>>, NDSpace<T, R> {
|
|||||||
* @param arg the multiplier.
|
* @param arg the multiplier.
|
||||||
* @return the product.
|
* @return the product.
|
||||||
*/
|
*/
|
||||||
public operator fun T.times(arg: NDStructure<T>): NDStructure<T> = map(arg) { value -> multiply(this@times, value) }
|
public operator fun T.times(arg: NDStructure<T>): NDStructure<T> = arg.map() { value -> multiply(this@times, value) }
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
@ -219,7 +219,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>
|
|||||||
* @param arg the divisor.
|
* @param arg the divisor.
|
||||||
* @return the quotient.
|
* @return the quotient.
|
||||||
*/
|
*/
|
||||||
public operator fun NDStructure<T>.div(arg: T): NDStructure<T> = map(this) { value -> divide(arg, value) }
|
public operator fun NDStructure<T>.div(arg: T): NDStructure<T> = this.map() { value -> divide(arg, value) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divides an element by an ND structure of it.
|
* Divides an element by an ND structure of it.
|
||||||
@ -228,7 +228,7 @@ public interface NDField<T, F : Field<T>> : Field<NDStructure<T>>, NDRing<T, F>
|
|||||||
* @param arg the divisor.
|
* @param arg the divisor.
|
||||||
* @return the quotient.
|
* @return the quotient.
|
||||||
*/
|
*/
|
||||||
public operator fun T.div(arg: NDStructure<T>): NDStructure<T> = map(arg) { divide(it, this@div) }
|
public operator fun T.div(arg: NDStructure<T>): NDStructure<T> = arg.map() { divide(it, this@div) }
|
||||||
|
|
||||||
// @ThreadLocal
|
// @ThreadLocal
|
||||||
// public companion object {
|
// public companion object {
|
||||||
|
@ -35,16 +35,15 @@ public class RealNDField(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE")
|
@Suppress("OVERRIDE_BY_INLINE")
|
||||||
override inline fun map(
|
override inline fun NDStructure<Double>.map(
|
||||||
arg: NDStructure<Double>,
|
|
||||||
transform: RealField.(Double) -> Double,
|
transform: RealField.(Double) -> Double,
|
||||||
): NDBuffer<Double> {
|
): NDBuffer<Double> {
|
||||||
val buffer = RealBuffer(strides.linearSize) { offset -> RealField.transform(arg.buffer.array[offset]) }
|
val buffer = RealBuffer(strides.linearSize) { offset -> RealField.transform(buffer.array[offset]) }
|
||||||
return NDBuffer(strides, buffer)
|
return NDBuffer(strides, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE")
|
@Suppress("OVERRIDE_BY_INLINE")
|
||||||
override inline fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer<Double> {
|
override inline fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer<Double> {
|
||||||
val array = DoubleArray(strides.linearSize) { offset ->
|
val array = DoubleArray(strides.linearSize) { offset ->
|
||||||
val index = strides.index(offset)
|
val index = strides.index(offset)
|
||||||
RealField.initializer(index)
|
RealField.initializer(index)
|
||||||
@ -53,15 +52,14 @@ public class RealNDField(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE")
|
@Suppress("OVERRIDE_BY_INLINE")
|
||||||
override inline fun mapIndexed(
|
override inline fun NDStructure<Double>.mapIndexed(
|
||||||
arg: NDStructure<Double>,
|
|
||||||
transform: RealField.(index: IntArray, Double) -> Double,
|
transform: RealField.(index: IntArray, Double) -> Double,
|
||||||
): NDBuffer<Double> = NDBuffer(
|
): NDBuffer<Double> = NDBuffer(
|
||||||
strides,
|
strides,
|
||||||
buffer = RealBuffer(strides.linearSize) { offset ->
|
buffer = RealBuffer(strides.linearSize) { offset ->
|
||||||
RealField.transform(
|
RealField.transform(
|
||||||
strides.index(offset),
|
strides.index(offset),
|
||||||
arg.buffer.array[offset]
|
buffer.array[offset]
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -70,32 +68,32 @@ public class RealNDField(
|
|||||||
a: NDStructure<Double>,
|
a: NDStructure<Double>,
|
||||||
b: NDStructure<Double>,
|
b: NDStructure<Double>,
|
||||||
transform: RealField.(Double, Double) -> Double,
|
transform: RealField.(Double, Double) -> Double,
|
||||||
): NDBuffer<Double> {
|
): NDBuffer<Double> {
|
||||||
val buffer = RealBuffer(strides.linearSize) { offset ->
|
val buffer = RealBuffer(strides.linearSize) { offset ->
|
||||||
RealField.transform(a.buffer.array[offset], b.buffer.array[offset])
|
RealField.transform(a.buffer.array[offset], b.buffer.array[offset])
|
||||||
}
|
}
|
||||||
return NDBuffer(strides, buffer)
|
return NDBuffer(strides, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = map(arg) { power(it, pow) }
|
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map { power(it, pow) }
|
||||||
|
|
||||||
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { exp(it) }
|
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { exp(it) }
|
||||||
|
|
||||||
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { ln(it) }
|
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { ln(it) }
|
||||||
|
|
||||||
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { sin(it) }
|
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sin(it) }
|
||||||
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { cos(it) }
|
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cos(it) }
|
||||||
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { tan(it) }
|
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tan(it) }
|
||||||
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { asin(it) }
|
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { asin(it) }
|
||||||
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { acos(it) }
|
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { acos(it) }
|
||||||
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { atan(it) }
|
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { atan(it) }
|
||||||
|
|
||||||
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { sinh(it) }
|
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { sinh(it) }
|
||||||
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { cosh(it) }
|
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { cosh(it) }
|
||||||
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { tanh(it) }
|
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { tanh(it) }
|
||||||
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { asinh(it) }
|
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { asinh(it) }
|
||||||
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { acosh(it) }
|
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { acosh(it) }
|
||||||
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = map(arg) { atanh(it) }
|
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun NDAlgebra.Companion.real(vararg shape: Int): RealNDField = RealNDField(shape)
|
public fun NDAlgebra.Companion.real(vararg shape: Int): RealNDField = RealNDField(shape)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package kscience.kmath.nd
|
package kscience.kmath.nd
|
||||||
|
|
||||||
import kscience.kmath.linear.Matrix
|
import kscience.kmath.linear.BufferMatrix
|
||||||
|
import kscience.kmath.linear.RealMatrixContext
|
||||||
import kscience.kmath.structures.Buffer
|
import kscience.kmath.structures.Buffer
|
||||||
import kscience.kmath.structures.VirtualBuffer
|
import kscience.kmath.structures.VirtualBuffer
|
||||||
|
|
||||||
@ -58,9 +59,9 @@ public interface Structure2D<T> : NDStructure<T> {
|
|||||||
rows: Int,
|
rows: Int,
|
||||||
columns: Int,
|
columns: Int,
|
||||||
crossinline init: (i: Int, j: Int) -> Double,
|
crossinline init: (i: Int, j: Int) -> Double,
|
||||||
): Matrix<Double> = NDAlgebra.real(rows, columns).produce { (i, j) ->
|
): BufferMatrix<Double> = RealMatrixContext.produce(rows,columns) { i, j ->
|
||||||
init(i, j)
|
init(i, j)
|
||||||
}.as2D()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ public fun RealMatrix.min(): Double? = elements().map { (_, value) -> value }.mi
|
|||||||
public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull()
|
public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull()
|
||||||
public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average()
|
public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average()
|
||||||
|
|
||||||
public inline fun RealMatrix.map(transform: (Double) -> Double): RealMatrix =
|
public inline fun RealMatrix.map(crossinline transform: (Double) -> Double): RealMatrix =
|
||||||
MatrixContext.real.produce(rowNum, colNum) { i, j ->
|
MatrixContext.real.produce(rowNum, colNum) { i, j ->
|
||||||
transform(get(i, j))
|
transform(get(i, j))
|
||||||
}
|
}
|
||||||
|
@ -44,18 +44,17 @@ public interface Nd4jArrayAlgebra<T, C> : NDAlgebra<T, C> {
|
|||||||
return struct
|
return struct
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun map(arg: NDStructure<T>, transform: C.(T) -> T): Nd4jArrayStructure<T> {
|
public override fun NDStructure<T>.map(transform: C.(T) -> T): Nd4jArrayStructure<T> {
|
||||||
val newStruct = arg.ndArray.dup().wrap()
|
val newStruct = ndArray.dup().wrap()
|
||||||
newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) }
|
newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) }
|
||||||
return newStruct
|
return newStruct
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun mapIndexed(
|
public override fun NDStructure<T>.mapIndexed(
|
||||||
arg: NDStructure<T>,
|
|
||||||
transform: C.(index: IntArray, T) -> T,
|
transform: C.(index: IntArray, T) -> T,
|
||||||
): Nd4jArrayStructure<T> {
|
): Nd4jArrayStructure<T> {
|
||||||
val new = Nd4j.create(*shape).wrap()
|
val new = Nd4j.create(*this@Nd4jArrayAlgebra.shape).wrap()
|
||||||
new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, arg[idx]) }
|
new.indicesIterator().forEach { idx -> new[idx] = elementContext.transform(idx, this[idx]) }
|
||||||
return new
|
return new
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package kscience.kmath.nd4j
|
package kscience.kmath.nd4j
|
||||||
|
|
||||||
import org.nd4j.linalg.factory.Nd4j
|
|
||||||
import kscience.kmath.operations.invoke
|
import kscience.kmath.operations.invoke
|
||||||
|
import org.nd4j.linalg.factory.Nd4j
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.fail
|
import kotlin.test.fail
|
||||||
@ -20,7 +20,7 @@ internal class Nd4jArrayAlgebraTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMap() {
|
fun testMap() {
|
||||||
val res = (IntNd4jArrayRing(intArrayOf(2, 2))) { map(one) { it + it * 2 } }
|
val res = (IntNd4jArrayRing(intArrayOf(2, 2))) { one.map() { it + it * 2 } }
|
||||||
val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure()
|
val expected = (Nd4j.create(2, 2) ?: fail()).asIntStructure()
|
||||||
expected[intArrayOf(0, 0)] = 3
|
expected[intArrayOf(0, 0)] = 3
|
||||||
expected[intArrayOf(0, 1)] = 3
|
expected[intArrayOf(0, 1)] = 3
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package kscience.kmath.viktor
|
package kscience.kmath.viktor
|
||||||
|
|
||||||
|
import kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kscience.kmath.nd.*
|
import kscience.kmath.nd.*
|
||||||
|
import kscience.kmath.operations.ExtendedField
|
||||||
import kscience.kmath.operations.RealField
|
import kscience.kmath.operations.RealField
|
||||||
|
import kscience.kmath.operations.RingWithNumbers
|
||||||
import org.jetbrains.bio.viktor.F64Array
|
import org.jetbrains.bio.viktor.F64Array
|
||||||
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
@ -20,8 +23,10 @@ public inline class ViktorNDStructure(public val f64Buffer: F64Array) : MutableN
|
|||||||
|
|
||||||
public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this)
|
public fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this)
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
@Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
|
||||||
public class ViktorNDField(public override val shape: IntArray) : NDField<Double, RealField> {
|
public class ViktorNDField(public override val shape: IntArray) : NDField<Double, RealField>,
|
||||||
|
RingWithNumbers<NDStructure<Double>>, ExtendedField<NDStructure<Double>> {
|
||||||
|
|
||||||
public val NDStructure<Double>.f64Buffer: F64Array
|
public val NDStructure<Double>.f64Buffer: F64Array
|
||||||
get() = when {
|
get() = when {
|
||||||
@ -50,26 +55,25 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
|
|||||||
}
|
}
|
||||||
}.asStructure()
|
}.asStructure()
|
||||||
|
|
||||||
public override fun map(arg: NDStructure<Double>, transform: RealField.(Double) -> Double): ViktorNDStructure =
|
public override fun NDStructure<Double>.map(transform: RealField.(Double) -> Double): ViktorNDStructure =
|
||||||
F64Array(*shape).apply {
|
F64Array(*this@ViktorNDField.shape).apply {
|
||||||
this@ViktorNDField.strides.indices().forEach { index ->
|
this@ViktorNDField.strides.indices().forEach { index ->
|
||||||
set(value = RealField.transform(arg[index]), indices = index)
|
set(value = RealField.transform(this@map[index]), indices = index)
|
||||||
}
|
}
|
||||||
}.asStructure()
|
}.asStructure()
|
||||||
|
|
||||||
public override fun mapIndexed(
|
public override fun NDStructure<Double>.mapIndexed(
|
||||||
arg: NDStructure<Double>,
|
transform: RealField.(index: IntArray, Double) -> Double,
|
||||||
transform: RealField.(index: IntArray, Double) -> Double
|
): ViktorNDStructure = F64Array(*this@ViktorNDField.shape).apply {
|
||||||
): ViktorNDStructure = F64Array(*shape).apply {
|
|
||||||
this@ViktorNDField.strides.indices().forEach { index ->
|
this@ViktorNDField.strides.indices().forEach { index ->
|
||||||
set(value = RealField.transform(index, arg[index]), indices = index)
|
set(value = RealField.transform(index, this@mapIndexed[index]), indices = index)
|
||||||
}
|
}
|
||||||
}.asStructure()
|
}.asStructure()
|
||||||
|
|
||||||
public override fun combine(
|
public override fun combine(
|
||||||
a: NDStructure<Double>,
|
a: NDStructure<Double>,
|
||||||
b: NDStructure<Double>,
|
b: NDStructure<Double>,
|
||||||
transform: RealField.(Double, Double) -> Double
|
transform: RealField.(Double, Double) -> Double,
|
||||||
): ViktorNDStructure = F64Array(*shape).apply {
|
): ViktorNDStructure = F64Array(*shape).apply {
|
||||||
this@ViktorNDField.strides.indices().forEach { index ->
|
this@ViktorNDField.strides.indices().forEach { index ->
|
||||||
set(value = RealField.transform(a[index], b[index]), indices = index)
|
set(value = RealField.transform(a[index], b[index]), indices = index)
|
||||||
@ -93,6 +97,25 @@ public class ViktorNDField(public override val shape: IntArray) : NDField<Double
|
|||||||
|
|
||||||
public override inline fun NDStructure<Double>.plus(arg: Double): ViktorNDStructure =
|
public override inline fun NDStructure<Double>.plus(arg: Double): ViktorNDStructure =
|
||||||
(f64Buffer.plus(arg)).asStructure()
|
(f64Buffer.plus(arg)).asStructure()
|
||||||
|
|
||||||
|
override fun number(value: Number): ViktorNDStructure =
|
||||||
|
F64Array.full(init = value.toDouble(), shape = shape).asStructure()
|
||||||
|
|
||||||
|
override fun sin(arg: NDStructure<Double>): ViktorNDStructure = arg.map { sin(it) }
|
||||||
|
|
||||||
|
override fun cos(arg: NDStructure<Double>): ViktorNDStructure = arg.map { cos(it) }
|
||||||
|
|
||||||
|
override fun asin(arg: NDStructure<Double>): ViktorNDStructure = arg.map { asin(it) }
|
||||||
|
|
||||||
|
override fun acos(arg: NDStructure<Double>): ViktorNDStructure = arg.map { acos(it) }
|
||||||
|
|
||||||
|
override fun atan(arg: NDStructure<Double>): ViktorNDStructure = arg.map { atan(it) }
|
||||||
|
|
||||||
|
override fun power(arg: NDStructure<Double>, pow: Number): ViktorNDStructure = arg.map { it.pow(pow) }
|
||||||
|
|
||||||
|
override fun exp(arg: NDStructure<Double>): ViktorNDStructure = arg.f64Buffer.exp().asStructure()
|
||||||
|
|
||||||
|
override fun ln(arg: NDStructure<Double>): ViktorNDStructure = arg.f64Buffer.log().asStructure()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ViktorNDField(vararg shape: Int): ViktorNDField = ViktorNDField(shape)
|
public fun ViktorNDField(vararg shape: Int): ViktorNDField = ViktorNDField(shape)
|
Loading…
Reference in New Issue
Block a user