forked from kscience/kmath
Merge remote-tracking branch 'origin/dev' into adv-expr
# Conflicts: # examples/build.gradle.kts
This commit is contained in:
commit
002de8d23a
@ -2,7 +2,7 @@ plugins {
|
||||
id("scientifik.publish") apply false
|
||||
}
|
||||
|
||||
val kmathVersion by extra("0.1.4-dev-7")
|
||||
val kmathVersion by extra("0.1.4-dev-8")
|
||||
|
||||
val bintrayRepo by extra("scientifik")
|
||||
val githubProject by extra("kmath")
|
||||
|
22
docs/codestyle.md
Normal file
22
docs/codestyle.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Local coding conventions
|
||||
|
||||
Kmath and other `scientifik` projects use general [kotlin code conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but with a number of small changes and clarifications.
|
||||
|
||||
## Utility class names
|
||||
File name should coincide with a name of one of the classes contained in the file or start with small letter and describe its contents.
|
||||
|
||||
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that file names should start with capital letter even if file does not contain classes. Yet starting utility classes and aggregators with a small letter seems to be a good way to clearly visually separate those files.
|
||||
|
||||
This convention could be changed in future in a non-breaking way.
|
||||
|
||||
## Private variable names
|
||||
Private variable names could start with underscore `_` in case the private mutable variable is shadowed by the public read-only value with the same meaning.
|
||||
|
||||
Code convention do not permit underscores in names, but is is sometimes useful to "underscore" the fact that public and private versions define the same entity. It is allowed only for private variables.
|
||||
|
||||
This convention could be changed in future in a non-breaking way.
|
||||
|
||||
## Functions and properties one-liners
|
||||
Use one-liners when they occupy single code window line both for functions and properties with getters like `val b: String get() = "fff"`. The same should be done with multiline expressions when they could be cleanly separated.
|
||||
|
||||
There is not general consensus whenever use `fun a() = {}` or `fun a(){return}`. Yet from reader perspective one-lines seem to better show that the property or function is easily calculated.
|
@ -1,13 +1,16 @@
|
||||
import org.jetbrains.kotlin.allopen.gradle.AllOpenExtension
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
java
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.allopen")
|
||||
id("kotlinx.benchmark")
|
||||
kotlin("plugin.allopen") version "1.3.72"
|
||||
id("kotlinx.benchmark") version "0.2.0-dev-8"
|
||||
}
|
||||
|
||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||
configure<AllOpenExtension> {
|
||||
annotation("org.openjdk.jmh.annotations.State")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("http://dl.bintray.com/kyonifer/maven")
|
||||
@ -21,7 +24,6 @@ sourceSets {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":kmath-ast"))
|
||||
implementation(project(":kmath-core"))
|
||||
implementation(project(":kmath-coroutines"))
|
||||
implementation(project(":kmath-commons"))
|
||||
@ -31,8 +33,8 @@ dependencies {
|
||||
implementation(project(":kmath-dimensions"))
|
||||
implementation("com.kyonifer:koma-core-ejml:0.12")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-7")
|
||||
"benchmarksCompile"(sourceSets.main.get().compileClasspath)
|
||||
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-8")
|
||||
"benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath
|
||||
}
|
||||
|
||||
// Configure benchmark
|
||||
|
@ -20,7 +20,7 @@ class ViktorBenchmark {
|
||||
final val viktorField = ViktorNDField(intArrayOf(dim, dim))
|
||||
|
||||
@Benchmark
|
||||
fun `Automatic field addition`() {
|
||||
fun automaticFieldAddition() {
|
||||
autoField.run {
|
||||
var res = one
|
||||
repeat(n) { res += one }
|
||||
@ -28,7 +28,7 @@ class ViktorBenchmark {
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun `Viktor field addition`() {
|
||||
fun viktorFieldAddition() {
|
||||
viktorField.run {
|
||||
var res = one
|
||||
repeat(n) { res += one }
|
||||
@ -36,14 +36,14 @@ class ViktorBenchmark {
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun `Raw Viktor`() {
|
||||
fun rawViktor() {
|
||||
val one = F64Array.full(init = 1.0, shape = *intArrayOf(dim, dim))
|
||||
var res = one
|
||||
repeat(n) { res = res + one }
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun `Real field log`() {
|
||||
fun realdFieldLog() {
|
||||
realField.run {
|
||||
val fortyTwo = produce { 42.0 }
|
||||
var res = one
|
||||
@ -52,7 +52,7 @@ class ViktorBenchmark {
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
fun `Raw Viktor log`() {
|
||||
fun rawViktorLog() {
|
||||
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
|
||||
var res: F64Array
|
||||
repeat(n) {
|
||||
|
@ -0,0 +1,38 @@
|
||||
package scientifik.kmath.commons.random
|
||||
|
||||
import scientifik.kmath.prob.RandomGenerator
|
||||
|
||||
class CMRandomGeneratorWrapper(val factory: (IntArray) -> RandomGenerator) :
|
||||
org.apache.commons.math3.random.RandomGenerator {
|
||||
private var generator = factory(intArrayOf())
|
||||
|
||||
override fun nextBoolean(): Boolean = generator.nextBoolean()
|
||||
|
||||
override fun nextFloat(): Float = generator.nextDouble().toFloat()
|
||||
|
||||
override fun setSeed(seed: Int) {
|
||||
generator = factory(intArrayOf(seed))
|
||||
}
|
||||
|
||||
override fun setSeed(seed: IntArray) {
|
||||
generator = factory(seed)
|
||||
}
|
||||
|
||||
override fun setSeed(seed: Long) {
|
||||
setSeed(seed.toInt())
|
||||
}
|
||||
|
||||
override fun nextBytes(bytes: ByteArray) {
|
||||
generator.fillBytes(bytes)
|
||||
}
|
||||
|
||||
override fun nextInt(): Int = generator.nextInt()
|
||||
|
||||
override fun nextInt(n: Int): Int = generator.nextInt(n)
|
||||
|
||||
override fun nextGaussian(): Double = TODO()
|
||||
|
||||
override fun nextDouble(): Double = generator.nextDouble()
|
||||
|
||||
override fun nextLong(): Long = generator.nextLong()
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package scientifik.kmath.domains
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
|
||||
/**
|
||||
* A simple geometric domain
|
||||
*/
|
||||
interface Domain<T : Any> {
|
||||
operator fun contains(point: Point<T>): Boolean
|
||||
|
||||
/**
|
||||
* Number of hyperspace dimensions
|
||||
*/
|
||||
val dimension: Int
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2015 Alexander Nozik.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package scientifik.kmath.domains
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
import scientifik.kmath.structures.indices
|
||||
|
||||
/**
|
||||
*
|
||||
* HyperSquareDomain class.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
class HyperSquareDomain(private val lower: DoubleBuffer, private val upper: DoubleBuffer) : RealDomain {
|
||||
|
||||
override operator fun contains(point: Point<Double>): Boolean = point.indices.all { i ->
|
||||
point[i] in lower[i]..upper[i]
|
||||
}
|
||||
|
||||
override val dimension: Int get() = lower.size
|
||||
|
||||
override fun getLowerBound(num: Int, point: Point<Double>): Double? = lower[num]
|
||||
|
||||
override fun getLowerBound(num: Int): Double? = lower[num]
|
||||
|
||||
override fun getUpperBound(num: Int, point: Point<Double>): Double? = upper[num]
|
||||
|
||||
override fun getUpperBound(num: Int): Double? = upper[num]
|
||||
|
||||
override fun nearestInDomain(point: Point<Double>): Point<Double> {
|
||||
val res: DoubleArray = DoubleArray(point.size) { i ->
|
||||
when {
|
||||
point[i] < lower[i] -> lower[i]
|
||||
point[i] > upper[i] -> upper[i]
|
||||
else -> point[i]
|
||||
}
|
||||
}
|
||||
return DoubleBuffer(*res)
|
||||
}
|
||||
|
||||
override fun volume(): Double {
|
||||
var res = 1.0
|
||||
for (i in 0 until dimension) {
|
||||
if (lower[i].isInfinite() || upper[i].isInfinite()) {
|
||||
return Double.POSITIVE_INFINITY
|
||||
}
|
||||
if (upper[i] > lower[i]) {
|
||||
res *= upper[i] - lower[i]
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2015 Alexander Nozik.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package scientifik.kmath.domains
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
|
||||
/**
|
||||
* n-dimensional volume
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
interface RealDomain: Domain<Double> {
|
||||
|
||||
fun nearestInDomain(point: Point<Double>): Point<Double>
|
||||
|
||||
/**
|
||||
* The lower edge for the domain going down from point
|
||||
* @param num
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
fun getLowerBound(num: Int, point: Point<Double>): Double?
|
||||
|
||||
/**
|
||||
* The upper edge of the domain going up from point
|
||||
* @param num
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
fun getUpperBound(num: Int, point: Point<Double>): Double?
|
||||
|
||||
/**
|
||||
* Global lower edge
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
fun getLowerBound(num: Int): Double?
|
||||
|
||||
/**
|
||||
* Global upper edge
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
fun getUpperBound(num: Int): Double?
|
||||
|
||||
/**
|
||||
* Hyper volume
|
||||
* @return
|
||||
*/
|
||||
fun volume(): Double
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2015 Alexander Nozik.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package scientifik.kmath.domains
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
|
||||
class UnconstrainedDomain(override val dimension: Int) : RealDomain {
|
||||
|
||||
override operator fun contains(point: Point<Double>): Boolean = true
|
||||
|
||||
override fun getLowerBound(num: Int, point: Point<Double>): Double? = Double.NEGATIVE_INFINITY
|
||||
|
||||
override fun getLowerBound(num: Int): Double? = Double.NEGATIVE_INFINITY
|
||||
|
||||
override fun getUpperBound(num: Int, point: Point<Double>): Double? = Double.POSITIVE_INFINITY
|
||||
|
||||
override fun getUpperBound(num: Int): Double? = Double.POSITIVE_INFINITY
|
||||
|
||||
override fun nearestInDomain(point: Point<Double>): Point<Double> = point
|
||||
|
||||
override fun volume(): Double = Double.POSITIVE_INFINITY
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package scientifik.kmath.domains
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
import scientifik.kmath.structures.asBuffer
|
||||
|
||||
inline class UnivariateDomain(val range: ClosedFloatingPointRange<Double>) : RealDomain {
|
||||
|
||||
operator fun contains(d: Double): Boolean = range.contains(d)
|
||||
|
||||
override operator fun contains(point: Point<Double>): Boolean {
|
||||
require(point.size == 0)
|
||||
return contains(point[0])
|
||||
}
|
||||
|
||||
override fun nearestInDomain(point: Point<Double>): Point<Double> {
|
||||
require(point.size == 1)
|
||||
val value = point[0]
|
||||
return when{
|
||||
value in range -> point
|
||||
value >= range.endInclusive -> doubleArrayOf(range.endInclusive).asBuffer()
|
||||
else -> doubleArrayOf(range.start).asBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLowerBound(num: Int, point: Point<Double>): Double? {
|
||||
require(num == 0)
|
||||
return range.start
|
||||
}
|
||||
|
||||
override fun getUpperBound(num: Int, point: Point<Double>): Double? {
|
||||
require(num == 0)
|
||||
return range.endInclusive
|
||||
}
|
||||
|
||||
override fun getLowerBound(num: Int): Double? {
|
||||
require(num == 0)
|
||||
return range.start
|
||||
}
|
||||
|
||||
override fun getUpperBound(num: Int): Double? {
|
||||
require(num == 0)
|
||||
return range.endInclusive
|
||||
}
|
||||
|
||||
override fun volume(): Double = range.endInclusive - range.start
|
||||
|
||||
override val dimension: Int get() = 1
|
||||
}
|
@ -12,26 +12,23 @@ import scientifik.kmath.structures.asBuffer
|
||||
import scientifik.kmath.structures.asIterable
|
||||
import kotlin.math.sqrt
|
||||
|
||||
typealias RealPoint = Point<Double>
|
||||
|
||||
fun DoubleArray.asVector() = RealVector(this.asBuffer())
|
||||
fun List<Double>.asVector() = RealVector(this.asBuffer())
|
||||
|
||||
|
||||
object VectorL2Norm : Norm<Point<out Number>, Double> {
|
||||
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble { it.toDouble() })
|
||||
}
|
||||
|
||||
inline class RealVector(private val point: Point<Double>) :
|
||||
SpaceElement<Point<Double>, RealVector, VectorSpace<Double, RealField>>, Point<Double> {
|
||||
SpaceElement<RealPoint, RealVector, VectorSpace<Double, RealField>>, RealPoint {
|
||||
|
||||
override val context: VectorSpace<Double, RealField>
|
||||
get() = space(
|
||||
point.size
|
||||
)
|
||||
override val context: VectorSpace<Double, RealField> get() = space(point.size)
|
||||
|
||||
override fun unwrap(): Point<Double> = point
|
||||
override fun unwrap(): RealPoint = point
|
||||
|
||||
override fun Point<Double>.wrap(): RealVector =
|
||||
RealVector(this)
|
||||
override fun RealPoint.wrap(): RealVector = RealVector(this)
|
||||
|
||||
override val size: Int get() = point.size
|
||||
|
||||
@ -48,12 +45,8 @@ inline class RealVector(private val point: Point<Double>) :
|
||||
|
||||
operator fun invoke(vararg values: Double): RealVector = values.asVector()
|
||||
|
||||
fun space(dim: Int): BufferVectorSpace<Double, RealField> =
|
||||
spaceCache.getOrPut(dim) {
|
||||
BufferVectorSpace(
|
||||
dim,
|
||||
RealField
|
||||
) { size, init -> Buffer.real(size, init) }
|
||||
}
|
||||
fun space(dim: Int): BufferVectorSpace<Double, RealField> = spaceCache.getOrPut(dim) {
|
||||
BufferVectorSpace(dim, RealField) { size, init -> Buffer.real(size, init) }
|
||||
}
|
||||
}
|
||||
}
|
@ -27,6 +27,10 @@ typealias RealMatrix = Matrix<Double>
|
||||
fun realMatrix(rowNum: Int, colNum: Int, initializer: (i: Int, j: Int) -> Double): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum, initializer)
|
||||
|
||||
fun Array<DoubleArray>.toMatrix(): RealMatrix{
|
||||
return MatrixContext.real.produce(size, this[0].size) { row, col -> this[row][col] }
|
||||
}
|
||||
|
||||
fun Sequence<DoubleArray>.toMatrix(): RealMatrix = toList().let {
|
||||
MatrixContext.real.produce(it.size, it[0].size) { row, col -> it[row][col] }
|
||||
}
|
||||
|
@ -1,18 +1,10 @@
|
||||
package scientifik.kmath.histogram
|
||||
|
||||
import scientifik.kmath.domains.Domain
|
||||
import scientifik.kmath.linear.Point
|
||||
import scientifik.kmath.structures.ArrayBuffer
|
||||
import scientifik.kmath.structures.DoubleBuffer
|
||||
|
||||
/**
|
||||
* A simple geometric domain
|
||||
* TODO move to geometry module
|
||||
*/
|
||||
interface Domain<T : Any> {
|
||||
operator fun contains(vector: Point<out T>): Boolean
|
||||
val dimension: Int
|
||||
}
|
||||
|
||||
/**
|
||||
* The bin in the histogram. The histogram is by definition always done in the real space
|
||||
*/
|
||||
|
@ -1,8 +1,8 @@
|
||||
package scientifik.kmath.histogram
|
||||
|
||||
import scientifik.kmath.linear.Point
|
||||
import scientifik.kmath.real.asVector
|
||||
import scientifik.kmath.operations.SpaceOperations
|
||||
import scientifik.kmath.real.asVector
|
||||
import scientifik.kmath.structures.*
|
||||
import kotlin.math.floor
|
||||
|
||||
@ -21,7 +21,7 @@ data class BinDef<T : Comparable<T>>(val space: SpaceOperations<Point<T>>, val c
|
||||
|
||||
class MultivariateBin<T : Comparable<T>>(val def: BinDef<T>, override val value: Number) : Bin<T> {
|
||||
|
||||
override fun contains(vector: Point<out T>): Boolean = def.contains(vector)
|
||||
override fun contains(point: Point<T>): Boolean = def.contains(point)
|
||||
|
||||
override val dimension: Int
|
||||
get() = def.center.size
|
||||
|
@ -16,7 +16,7 @@ class UnivariateBin(val position: Double, val size: Double, val counter: LongCou
|
||||
|
||||
operator fun contains(value: Double): Boolean = value in (position - size / 2)..(position + size / 2)
|
||||
|
||||
override fun contains(vector: Buffer<out Double>): Boolean = contains(vector[0])
|
||||
override fun contains(point: Buffer<Double>): Boolean = contains(point[0])
|
||||
|
||||
internal operator fun inc() = this.also { counter.increment() }
|
||||
|
||||
|
@ -10,6 +10,7 @@ interface MemorySpec<T : Any> {
|
||||
val objectSize: Int
|
||||
|
||||
fun MemoryReader.read(offset: Int): T
|
||||
//TODO consider thread safety
|
||||
fun MemoryWriter.write(offset: Int, value: T)
|
||||
}
|
||||
|
||||
|
@ -11,18 +11,16 @@ class DataViewMemory(val view: DataView) : Memory {
|
||||
override fun view(offset: Int, length: Int): Memory {
|
||||
require(offset >= 0) { "offset shouldn't be negative: $offset" }
|
||||
require(length >= 0) { "length shouldn't be negative: $length" }
|
||||
if (offset + length > size) {
|
||||
|
||||
if (offset + length > size)
|
||||
throw IndexOutOfBoundsException("offset + length > size: $offset + $length > $size")
|
||||
}
|
||||
|
||||
return DataViewMemory(DataView(view.buffer, view.byteOffset + offset, length))
|
||||
}
|
||||
|
||||
override fun copy(): Memory = DataViewMemory(DataView(view.buffer.slice(0)))
|
||||
|
||||
override fun copy(): Memory {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
private val reader = object : MemoryReader {
|
||||
private val reader: MemoryReader = object : MemoryReader {
|
||||
override val memory: Memory get() = this@DataViewMemory
|
||||
|
||||
override fun readDouble(offset: Int): Double = view.getFloat64(offset, false)
|
||||
@ -45,7 +43,7 @@ class DataViewMemory(val view: DataView) : Memory {
|
||||
|
||||
override fun reader(): MemoryReader = reader
|
||||
|
||||
private val writer = object : MemoryWriter {
|
||||
private val writer: MemoryWriter = object : MemoryWriter {
|
||||
override val memory: Memory get() = this@DataViewMemory
|
||||
|
||||
override fun writeDouble(offset: Int, value: Double) {
|
||||
@ -76,7 +74,6 @@ class DataViewMemory(val view: DataView) : Memory {
|
||||
override fun release() {
|
||||
//does nothing on JS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun writer(): MemoryWriter = writer
|
||||
@ -94,4 +91,4 @@ actual fun Memory.Companion.allocate(length: Int): Memory {
|
||||
actual fun Memory.Companion.wrap(array: ByteArray): Memory {
|
||||
@Suppress("CAST_NEVER_SUCCEEDS") val int8Array = array as Int8Array
|
||||
return DataViewMemory(DataView(int8Array.buffer, int8Array.byteOffset, int8Array.length))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user