Add API documentation, fix hashCode

This commit is contained in:
Iaroslav Postovalov 2020-12-20 00:06:40 +07:00
parent 386b063c94
commit cdebe2fc4f
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
6 changed files with 50 additions and 11 deletions

View File

@ -29,7 +29,7 @@ internal enum class GslErrnoValue(val code: Int, val text: String) {
GSL_EBADTOL(org.gnu.gsl.GSL_EBADTOL, "user specified an invalid tolerance"), GSL_EBADTOL(org.gnu.gsl.GSL_EBADTOL, "user specified an invalid tolerance"),
GSL_ETOL(org.gnu.gsl.GSL_ETOL, "failed to reach the specified tolerance"), GSL_ETOL(org.gnu.gsl.GSL_ETOL, "failed to reach the specified tolerance"),
GSL_EUNDRFLW(org.gnu.gsl.GSL_EUNDRFLW, "underflow"), GSL_EUNDRFLW(org.gnu.gsl.GSL_EUNDRFLW, "underflow"),
GSL_EOVRFLW(org.gnu.gsl.GSL_EOVRFLW, "overflow "), GSL_EOVRFLW(org.gnu.gsl.GSL_EOVRFLW, "overflow"),
GSL_ELOSS(org.gnu.gsl.GSL_ELOSS, "loss of accuracy"), GSL_ELOSS(org.gnu.gsl.GSL_ELOSS, "loss of accuracy"),
GSL_EROUND(org.gnu.gsl.GSL_EROUND, "failed because of roundoff error"), GSL_EROUND(org.gnu.gsl.GSL_EROUND, "failed because of roundoff error"),
GSL_EBADLEN(org.gnu.gsl.GSL_EBADLEN, "matrix, vector lengths are not conformant"), GSL_EBADLEN(org.gnu.gsl.GSL_EBADLEN, "matrix, vector lengths are not conformant"),
@ -54,7 +54,10 @@ internal enum class GslErrnoValue(val code: Int, val text: String) {
} }
} }
internal class GslException internal constructor(file: String, line: Int, reason: String, errno: Int) : /**
* Wraps all the errors reported by GSL.
*/
public class GslException internal constructor(file: String, line: Int, reason: String, errno: Int) :
RuntimeException("$file:$line: $reason. errno - $errno, ${GslErrnoValue.valueOf(errno)}") { RuntimeException("$file:$line: $reason. errno - $errno, ${GslErrnoValue.valueOf(errno)}") {
} }

View File

@ -5,6 +5,9 @@ import kotlinx.cinterop.DeferScope
import kscience.kmath.linear.FeaturedMatrix import kscience.kmath.linear.FeaturedMatrix
import kscience.kmath.structures.NDStructure import kscience.kmath.structures.NDStructure
/**
* Wraps gsl_matrix_* objects from GSL.
*/
public abstract class GslMatrix<T : Any, H : CStructVar> internal constructor(scope: DeferScope) : public abstract class GslMatrix<T : Any, H : CStructVar> internal constructor(scope: DeferScope) :
GslMemoryHolder<H>(scope), GslMemoryHolder<H>(scope),
FeaturedMatrix<T> { FeaturedMatrix<T> {
@ -15,9 +18,17 @@ public abstract class GslMatrix<T : Any, H : CStructVar> internal constructor(sc
return NDStructure.equals(this, other as? NDStructure<*> ?: return false) return NDStructure.equals(this, other as? NDStructure<*> ?: return false)
} }
public final override fun hashCode(): Int { public override fun hashCode(): Int {
var result = nativeHandle.hashCode() var ret = 7
result = 31 * result + features.hashCode() val nRows = rowNum
return result val nCols = colNum
ret = ret * 31 + nRows
ret = ret * 31 + nCols
for (row in 0 until nRows)
for (col in 0 until nCols)
ret = ret * 31 + (11 * (row + 1) + 17 * (col + 1)) * this[row, col].hashCode()
return ret
} }
} }

View File

@ -19,6 +19,9 @@ internal inline fun <T : Any, H : CStructVar> GslMatrix<T, H>.fill(initializer:
internal inline fun <T : Any, H : CStructVar> GslVector<T, H>.fill(initializer: (Int) -> T): GslVector<T, H> = internal inline fun <T : Any, H : CStructVar> GslVector<T, H>.fill(initializer: (Int) -> T): GslVector<T, H> =
apply { (0 until size).forEach { index -> this[index] = initializer(index) } } apply { (0 until size).forEach { index -> this[index] = initializer(index) } }
/**
* Represents matrix context implementing where all the operations are delegated to GSL.
*/
public abstract class GslMatrixContext<T : Any, H1 : CStructVar, H2 : CStructVar> internal constructor( public abstract class GslMatrixContext<T : Any, H1 : CStructVar, H2 : CStructVar> internal constructor(
internal val scope: DeferScope internal val scope: DeferScope
) : MatrixContext<T, GslMatrix<T, H1>> { ) : MatrixContext<T, GslMatrix<T, H1>> {
@ -26,12 +29,18 @@ public abstract class GslMatrixContext<T : Any, H1 : CStructVar, H2 : CStructVar
ensureHasGslErrorHandler() ensureHasGslErrorHandler()
} }
/**
* Converts this matrix to GSL one.
*/
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public fun Matrix<T>.toGsl(): GslMatrix<T, H1> = (if (this is GslMatrix<*, *>) public fun Matrix<T>.toGsl(): GslMatrix<T, H1> = (if (this is GslMatrix<*, *>)
this as GslMatrix<T, H1> this as GslMatrix<T, H1>
else else
produce(rowNum, colNum) { i, j -> this[i, j] }).copy() produce(rowNum, colNum) { i, j -> this[i, j] }).copy()
/**
* Converts this point to GSL one.
*/
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public fun Point<T>.toGsl(): GslVector<T, H2> = public fun Point<T>.toGsl(): GslVector<T, H2> =
(if (this is GslVector<*, *>) this as GslVector<T, H2> else produceDirtyVector(size).fill { this[it] }).copy() (if (this is GslVector<*, *>) this as GslVector<T, H2> else produceDirtyVector(size).fill { this[it] }).copy()
@ -43,6 +52,9 @@ public abstract class GslMatrixContext<T : Any, H1 : CStructVar, H2 : CStructVar
produceDirtyMatrix(rows, columns).fill(initializer) produceDirtyMatrix(rows, columns).fill(initializer)
} }
/**
* Represents [Double] matrix context implementing where all the operations are delegated to GSL.
*/
public class GslRealMatrixContext(scope: DeferScope) : GslMatrixContext<Double, gsl_matrix, gsl_vector>(scope) { public class GslRealMatrixContext(scope: DeferScope) : GslMatrixContext<Double, gsl_matrix, gsl_vector>(scope) {
override fun produceDirtyMatrix(rows: Int, columns: Int): GslMatrix<Double, gsl_matrix> = override fun produceDirtyMatrix(rows: Int, columns: Int): GslMatrix<Double, gsl_matrix> =
GslRealMatrix( GslRealMatrix(
@ -88,6 +100,9 @@ public class GslRealMatrixContext(scope: DeferScope) : GslMatrixContext<Double,
} }
} }
/**
* Represents [Float] matrix context implementing where all the operations are delegated to GSL.
*/
public class GslFloatMatrixContext(scope: DeferScope) : public class GslFloatMatrixContext(scope: DeferScope) :
GslMatrixContext<Float, gsl_matrix_float, gsl_vector_float>(scope) { GslMatrixContext<Float, gsl_matrix_float, gsl_vector_float>(scope) {
override fun produceDirtyMatrix(rows: Int, columns: Int): GslMatrix<Float, gsl_matrix_float> = override fun produceDirtyMatrix(rows: Int, columns: Int): GslMatrix<Float, gsl_matrix_float> =
@ -131,6 +146,9 @@ public class GslFloatMatrixContext(scope: DeferScope) :
} }
} }
/**
* Represents [Complex] matrix context implementing where all the operations are delegated to GSL.
*/
public class GslComplexMatrixContext(scope: DeferScope) : public class GslComplexMatrixContext(scope: DeferScope) :
GslMatrixContext<Complex, gsl_matrix_complex, gsl_vector_complex>(scope) { GslMatrixContext<Complex, gsl_matrix_complex, gsl_vector_complex>(scope) {
override fun produceDirtyMatrix(rows: Int, columns: Int): GslMatrix<Complex, gsl_matrix_complex> = override fun produceDirtyMatrix(rows: Int, columns: Int): GslMatrix<Complex, gsl_matrix_complex> =

View File

@ -4,6 +4,12 @@ import kotlinx.cinterop.CPointer
import kotlinx.cinterop.CStructVar import kotlinx.cinterop.CStructVar
import kotlinx.cinterop.DeferScope import kotlinx.cinterop.DeferScope
/**
* Represents managed native GSL object. The only property this class holds is pointer to the GSL object. In order to be
* freed this class's object must be added to [DeferScope].
*
* @param scope the scope where this object is declared.
*/
public abstract class GslMemoryHolder<H : CStructVar> internal constructor(internal val scope: DeferScope) { public abstract class GslMemoryHolder<H : CStructVar> internal constructor(internal val scope: DeferScope) {
internal abstract val nativeHandle: CPointer<H> internal abstract val nativeHandle: CPointer<H>

View File

@ -4,6 +4,9 @@ import kotlinx.cinterop.CStructVar
import kotlinx.cinterop.DeferScope import kotlinx.cinterop.DeferScope
import kscience.kmath.linear.Point import kscience.kmath.linear.Point
/**
* Wraps gsl_vector_* objects from GSL.
*/
public abstract class GslVector<T, H : CStructVar> internal constructor(scope: DeferScope) : public abstract class GslVector<T, H : CStructVar> internal constructor(scope: DeferScope) :
GslMemoryHolder<H>(scope), Point<T> { GslMemoryHolder<H>(scope), Point<T> {
internal abstract operator fun set(index: Int, value: T) internal abstract operator fun set(index: Int, value: T)

View File

@ -3,9 +3,7 @@ package kscience.kmath.gsl
import kotlinx.cinterop.memScoped import kotlinx.cinterop.memScoped
import kscience.kmath.linear.RealMatrixContext import kscience.kmath.linear.RealMatrixContext
import kscience.kmath.operations.invoke import kscience.kmath.operations.invoke
import kscience.kmath.structures.RealBuffer import kscience.kmath.structures.*
import kscience.kmath.structures.asIterable
import kscience.kmath.structures.asSequence
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -38,8 +36,8 @@ internal class RealTest {
(GslRealMatrixContext(this)) { (GslRealMatrixContext(this)) {
val ma = produce(2, 2) { _, _ -> 100.0 } val ma = produce(2, 2) { _, _ -> 100.0 }
val mb = produce(2, 2) { _, _ -> 100.0 } val mb = produce(2, 2) { _, _ -> 100.0 }
val res1 = ma dot mb val res1: Matrix<Double> = ma dot mb
val res2 = RealMatrixContext { ma dot mb } val res2: Matrix<Double> = RealMatrixContext { ma dot mb }
println(res1.rows.asIterable().map { it.asSequence() }.flatMap(Sequence<*>::toList)) println(res1.rows.asIterable().map { it.asSequence() }.flatMap(Sequence<*>::toList))
println(res2.rows.asIterable().map { it.asSequence() }.flatMap(Sequence<*>::toList)) println(res2.rows.asIterable().map { it.asSequence() }.flatMap(Sequence<*>::toList))
assertEquals(res1, res2) assertEquals(res1, res2)