Add @author annotations, minor KDoc updates #138
@ -6,6 +6,8 @@ import scientifik.kmath.operations.RealField
|
||||
|
||||
/**
|
||||
* A Mathematical Syntax Tree node for mathematical expressions.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
sealed class MST {
|
||||
/**
|
||||
@ -52,6 +54,7 @@ sealed class MST {
|
||||
* @receiver the algebra that provides operations.
|
||||
* @param node the node to evaluate.
|
||||
* @return the value of expression.
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
||||
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
|
||||
|
@ -4,6 +4,8 @@ import scientifik.kmath.operations.*
|
||||
|
||||
/**
|
||||
* [Algebra] over [MST] nodes.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
object MstAlgebra : NumericAlgebra<MST> {
|
||||
override fun number(value: Number): MST = MST.Numeric(value)
|
||||
@ -19,6 +21,8 @@ object MstAlgebra : NumericAlgebra<MST> {
|
||||
|
||||
/**
|
||||
* [Space] over [MST] nodes.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
||||
override val zero: MST = number(0.0)
|
||||
@ -36,6 +40,8 @@ object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
||||
|
||||
/**
|
||||
* [Ring] over [MST] nodes.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
||||
override val zero: MST = number(0.0)
|
||||
@ -57,6 +63,8 @@ object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
||||
|
||||
/**
|
||||
* [Field] over [MST] nodes.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
object MstField : Field<MST> {
|
||||
override val zero: MST = number(0.0)
|
||||
@ -77,6 +85,8 @@ object MstField : Field<MST> {
|
||||
|
||||
/**
|
||||
* [ExtendedField] over [MST] nodes.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
object MstExtendedField : ExtendedField<MST> {
|
||||
override val zero: MST = number(0.0)
|
||||
|
@ -11,6 +11,7 @@ import kotlin.contracts.contract
|
||||
*
|
||||
* @property algebra the algebra that provides operations.
|
||||
* @property mst the [MST] node.
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
class MstExpression<T>(val algebra: Algebra<T>, val mst: MST) : Expression<T> {
|
||||
private inner class InnerAlgebra(val arguments: Map<String, T>) : NumericAlgebra<T> {
|
||||
@ -31,6 +32,8 @@ class MstExpression<T>(val algebra: Algebra<T>, val mst: MST) : Expression<T> {
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [Algebra].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
|
||||
mstAlgebra: E,
|
||||
@ -39,6 +42,8 @@ inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [Space].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -47,6 +52,8 @@ inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): Mst
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [Ring].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -55,6 +62,8 @@ inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExp
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [Field].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -63,6 +72,8 @@ inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): Mst
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [ExtendedField].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -71,6 +82,8 @@ inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [FunctionalExpressionSpace].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -79,6 +92,8 @@ inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstIn
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [FunctionalExpressionRing].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -87,6 +102,8 @@ inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRi
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [FunctionalExpressionField].
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstInField(block: MstField.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -95,6 +112,8 @@ inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstIn
|
||||
|
||||
/**
|
||||
* Builds [MstExpression] over [FunctionalExpressionExtendedField].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
inline fun <reified T : Any, A : ExtendedField<T>> FunctionalExpressionExtendedField<T, A>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
|
@ -17,6 +17,8 @@ import scientifik.kmath.operations.SpaceOperations
|
||||
|
||||
/**
|
||||
* TODO move to core
|
||||
*
|
||||
* @author Alexander Nozik and Iaroslav Postovalov
|
||||
*/
|
||||
object ArithmeticsEvaluator : Grammar<MST>() {
|
||||
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
|
||||
@ -85,6 +87,7 @@ object ArithmeticsEvaluator : Grammar<MST>() {
|
||||
*
|
||||
* @receiver the string to parse.
|
||||
* @return the [MST] node.
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
|
||||
|
||||
@ -93,5 +96,6 @@ fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd
|
||||
*
|
||||
* @receiver the string to parse.
|
||||
* @return the [MST] node.
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this)
|
||||
|
@ -11,7 +11,12 @@ import scientifik.kmath.operations.Algebra
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Compile given MST to an Expression using AST compiler
|
||||
* Compiles given MST to an Expression using AST compiler.
|
||||
*
|
||||
* @param type the target type.
|
||||
* @param algebra the target algebra.
|
||||
* @return the compiled expression.
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<T> {
|
||||
fun AsmBuilder<T>.visit(node: MST) {
|
||||
@ -54,11 +59,15 @@ fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an [MST] to ASM using given algebra
|
||||
* Compiles an [MST] to ASM using given algebra.
|
||||
*
|
||||
* @author Alexander Nozik.
|
||||
*/
|
||||
inline fun <reified T : Any> Algebra<T>.expression(mst: MST): Expression<T> = mst.compileWith(T::class, this)
|
||||
|
||||
/**
|
||||
* Optimize performance of an [MstExpression] using ASM codegen
|
||||
* Optimizes performance of an [MstExpression] using ASM codegen.
|
||||
*
|
||||
* @author Alexander Nozik.
|
||||
*/
|
||||
inline fun <reified T : Any> MstExpression<T>.compile(): Expression<T> = mst.compileWith(T::class, algebra)
|
||||
|
@ -20,6 +20,7 @@ import kotlin.reflect.KClass
|
||||
* @property algebra the algebra the applied AsmExpressions use.
|
||||
* @property className the unique class name of new loaded class.
|
||||
* @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal class AsmBuilder<T> internal constructor(
|
||||
private val classOfT: KClass<*>,
|
||||
|
@ -2,6 +2,9 @@ package scientifik.kmath.asm.internal
|
||||
|
||||
import scientifik.kmath.ast.MST
|
||||
|
||||
/**
|
||||
* Represents types known in [MST], numbers and general values.
|
||||
*/
|
||||
internal enum class MstType {
|
||||
GENERAL,
|
||||
NUMBER;
|
||||
|
@ -6,6 +6,9 @@ import org.objectweb.asm.commons.InstructionAdapter
|
||||
import scientifik.kmath.ast.MST
|
||||
import scientifik.kmath.expressions.Expression
|
||||
import scientifik.kmath.operations.Algebra
|
||||
import scientifik.kmath.operations.FieldOperations
|
||||
import scientifik.kmath.operations.RingOperations
|
||||
import scientifik.kmath.operations.SpaceOperations
|
||||
import java.lang.reflect.Method
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
@ -13,20 +16,27 @@ import kotlin.reflect.KClass
|
||||
|
||||
private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
|
||||
hashMapOf(
|
||||
"+" to 2 to "add",
|
||||
"*" to 2 to "multiply",
|
||||
"/" to 2 to "divide",
|
||||
"+" to 1 to "unaryPlus",
|
||||
"-" to 1 to "unaryMinus",
|
||||
"-" to 2 to "minus"
|
||||
SpaceOperations.PLUS_OPERATION to 2 to "add",
|
||||
RingOperations.TIMES_OPERATION to 2 to "multiply",
|
||||
FieldOperations.DIV_OPERATION to 2 to "divide",
|
||||
SpaceOperations.PLUS_OPERATION to 1 to "unaryPlus",
|
||||
SpaceOperations.MINUS_OPERATION to 1 to "unaryMinus",
|
||||
SpaceOperations.MINUS_OPERATION to 2 to "minus"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ASM [Type] for given [KClass].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal val KClass<*>.asm: Type
|
||||
get() = Type.getType(java)
|
||||
|
||||
/**
|
||||
* Returns singleton array with this value if the [predicate] is true, returns empty array otherwise.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal inline fun <reified T> T.wrapToArrayIf(predicate: (T) -> Boolean): Array<T> {
|
||||
contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -35,11 +45,15 @@ internal inline fun <reified T> T.wrapToArrayIf(predicate: (T) -> Boolean): Arra
|
||||
|
||||
/**
|
||||
* Creates an [InstructionAdapter] from this [MethodVisitor].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
private fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this)
|
||||
|
||||
/**
|
||||
* Creates an [InstructionAdapter] from this [MethodVisitor] and applies [block] to it.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
@ -48,6 +62,8 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
|
||||
|
||||
/**
|
||||
* Constructs a [Label], then applies it to this visitor.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
|
||||
|
||||
@ -56,6 +72,8 @@ internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
|
||||
*
|
||||
* This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there
|
||||
* is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
|
||||
val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision"
|
||||
@ -75,6 +93,11 @@ internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): Clas
|
||||
return ClassWriter(flags).apply(block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes [visitField] and applies [block] to the [FieldVisitor].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal inline fun ClassWriter.visitField(
|
||||
access: Int,
|
||||
name: String,
|
||||
@ -104,7 +127,7 @@ private fun <T> AsmBuilder<T>.findSpecific(context: Algebra<T>, name: String, pa
|
||||
* Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds
|
||||
* type expectation stack for needed arity.
|
||||
*
|
||||
* @return `true` if contains, else `false`.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
private fun <T> AsmBuilder<T>.buildExpectationStack(
|
||||
context: Algebra<T>,
|
||||
@ -136,7 +159,7 @@ private fun <T> AsmBuilder<T>.mapTypes(method: Method, parameterTypes: Array<Mst
|
||||
* Checks if the target [context] for code generation contains a method with needed [name] and arity and inserts
|
||||
* [AsmBuilder.invokeAlgebraOperation] of this method.
|
||||
*
|
||||
* @return `true` if contains, else `false`.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
private fun <T> AsmBuilder<T>.tryInvokeSpecific(
|
||||
context: Algebra<T>,
|
||||
@ -160,7 +183,9 @@ private fun <T> AsmBuilder<T>.tryInvokeSpecific(
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds specialized algebra call with option to fallback to generic algebra operation accepting String.
|
||||
* Builds specialized [context] call with option to fallback to generic algebra operation accepting [String].
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
internal inline fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
|
||||
context: Algebra<T>,
|
||||
|
@ -2,6 +2,11 @@
|
||||
|
||||
package scientifik.kmath.asm.internal
|
||||
|
||||
/**
|
||||
* Gets value with given [key] or throws [IllegalStateException] whenever it is not present.
|
||||
*
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
@JvmOverloads
|
||||
internal fun <K, V> Map<K, V>.getOrFail(key: K, default: V? = null): V =
|
||||
this[key] ?: default ?: error("Parameter not found: $key")
|
||||
|
@ -24,6 +24,7 @@ fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, right -> ad
|
||||
* @receiver the algebra that provides addition and division.
|
||||
* @param data the iterable to find average.
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
||||
|
||||
@ -33,6 +34,7 @@ fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
||||
* @receiver the algebra that provides addition and division.
|
||||
* @param data the sequence to find average.
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
|
||||
|
||||
@ -60,6 +62,7 @@ fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
|
||||
* @receiver the iterable to find average.
|
||||
* @param space the algebra that provides addition and division.
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||
|
||||
@ -69,6 +72,7 @@ fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||
* @receiver the sequence to find average.
|
||||
* @param space the algebra that provides addition and division.
|
||||
* @return the average value.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||
|
||||
@ -98,6 +102,7 @@ fun <T> Ring<T>.power(arg: T, power: Int): T {
|
||||
* @param arg the base.
|
||||
* @param power the exponent.
|
||||
* @return the base raised to the power.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
fun <T> Field<T>.power(arg: T, power: Int): T {
|
||||
require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." }
|
||||
|
@ -6,6 +6,7 @@ import kotlin.contracts.contract
|
||||
* Specialized [MutableBuffer] implementation over [FloatArray].
|
||||
*
|
||||
* @property array the underlying array.
|
||||
* @author Iaroslav Postovalov
|
||||
*/
|
||||
inline class FloatBuffer(val array: FloatArray) : MutableBuffer<Float> {
|
||||
override val size: Int get() = array.size
|
||||
|
Loading…
Reference in New Issue
Block a user