Implement hyperbolic functions for various Algebras #118

Merged
CommanderTvis merged 14 commits from hyp-trig-functions into dev 2020-08-11 18:18:06 +03:00
5 changed files with 82 additions and 40 deletions
Showing only changes of commit 6ead822cc3 - Show all commits

View File

@ -84,9 +84,9 @@ object MstExtendedField : ExtendedField<MST> {
override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
override fun asin(arg: MST): MST = unaryOperation(InverseTrigonometricOperations.ASIN_OPERATION, arg)
override fun acos(arg: MST): MST = unaryOperation(InverseTrigonometricOperations.ACOS_OPERATION, arg)
override fun atan(arg: MST): MST = unaryOperation(InverseTrigonometricOperations.ATAN_OPERATION, arg)
override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
override fun add(a: MST, b: MST): MST = MstField.add(a, b)
override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k)
override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b)

View File

@ -139,15 +139,9 @@ open class FunctionalExpressionExtendedField<T, A>(algebra: A) :
ExtendedField<Expression<T>> where A : ExtendedField<T>, A : NumericAlgebra<T> {
override fun sin(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
override fun cos(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
override fun asin(arg: Expression<T>): Expression<T> =
unaryOperation(InverseTrigonometricOperations.ASIN_OPERATION, arg)
override fun acos(arg: Expression<T>): Expression<T> =
unaryOperation(InverseTrigonometricOperations.ACOS_OPERATION, arg)
override fun atan(arg: Expression<T>): Expression<T> =
unaryOperation(InverseTrigonometricOperations.ATAN_OPERATION, arg)
override fun asin(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
override fun acos(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
override fun atan(arg: Expression<T>): Expression<T> = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
override fun power(arg: Expression<T>, pow: Number): Expression<T> =
binaryOperation(PowerOperations.POW_OPERATION, arg, number(pow))

View File

@ -99,13 +99,6 @@ object ComplexField : ExtendedField<Complex> {
return i * (ln(1 - iArg) - ln(1 + iArg)) / 2
}
override fun sinh(arg: Complex): Complex = (exp(arg) - exp(-arg)) / 2
override fun cosh(arg: Complex): Complex = (exp(arg) + exp(-arg)) / 2
override fun tanh(arg: Complex): Complex = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
override fun asinh(arg: Complex): Complex = ln(sqrt(arg * arg + 1) + arg)
override fun acosh(arg: Complex): Complex = ln(arg + sqrt((arg - 1) * (arg + 1)))
override fun atanh(arg: Complex): Complex = (ln(arg + 1) - ln(1 - arg)) / 2
override fun power(arg: Complex, pow: Number): Complex = if (arg.im == 0.0)
arg.re.pow(pow.toDouble()).toComplex()
else
@ -199,7 +192,7 @@ data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Compl
* @receiver the real part.
* @return the new complex number.
*/
fun Number.toComplex() = Complex(this, 0.0)
fun Number.toComplex(): Complex = Complex(this, 0.0)
inline fun Buffer.Companion.complex(size: Int, crossinline init: (Int) -> Complex): Buffer<Complex> {
return MemoryBuffer.create(Complex, size, init)

View File

@ -7,8 +7,9 @@ import kotlin.math.pow as kpow
* Advanced Number-like semifield that implements basic operations.
*/
interface ExtendedFieldOperations<T> :
FieldOperations<T>,
TrigonometricOperations<T>,
HyperbolicTrigonometricOperations<T>,
HyperbolicOperations<T>,
PowerOperations<T>,
ExponentialOperations<T> {
@ -22,16 +23,16 @@ interface ExtendedFieldOperations<T> :
TrigonometricOperations.ACOS_OPERATION -> acos(arg)
TrigonometricOperations.ASIN_OPERATION -> asin(arg)
TrigonometricOperations.ATAN_OPERATION -> atan(arg)
HyperbolicTrigonometricOperations.COSH_OPERATION -> cosh(arg)
HyperbolicTrigonometricOperations.SINH_OPERATION -> sinh(arg)
HyperbolicTrigonometricOperations.TANH_OPERATION -> tanh(arg)
HyperbolicTrigonometricOperations.ACOSH_OPERATION -> acosh(arg)
HyperbolicTrigonometricOperations.ASINH_OPERATION -> asinh(arg)
HyperbolicTrigonometricOperations.ATANH_OPERATION -> atanh(arg)
HyperbolicOperations.COSH_OPERATION -> cosh(arg)
HyperbolicOperations.SINH_OPERATION -> sinh(arg)
HyperbolicOperations.TANH_OPERATION -> tanh(arg)
HyperbolicOperations.ACOSH_OPERATION -> acosh(arg)
HyperbolicOperations.ASINH_OPERATION -> asinh(arg)
HyperbolicOperations.ATANH_OPERATION -> atanh(arg)
PowerOperations.SQRT_OPERATION -> sqrt(arg)
ExponentialOperations.EXP_OPERATION -> exp(arg)
ExponentialOperations.LN_OPERATION -> ln(arg)
else -> super<HyperbolicTrigonometricOperations>.unaryOperation(operation, arg)
else -> super.unaryOperation(operation, arg)
}
}
@ -40,6 +41,13 @@ interface ExtendedFieldOperations<T> :
* Advanced Number-like field that implements basic operations.
*/
interface ExtendedField<T> : ExtendedFieldOperations<T>, Field<T> {
override fun sinh(arg: T): T = (exp(arg) - exp(-arg)) / 2
override fun cosh(arg: T): T = (exp(arg) + exp(-arg)) / 2
override fun tanh(arg: T): T = (exp(arg) - exp(-arg)) / (exp(-arg) + exp(arg))
override fun asinh(arg: T): T = ln(sqrt(arg * arg + one) + arg)
override fun acosh(arg: T): T = ln(arg + sqrt((arg - one) * (arg + one)))
override fun atanh(arg: T): T = (ln(arg + one) - ln(one - arg)) / 2
override fun rightSideNumberOperation(operation: String, left: T, right: Number): T = when (operation) {
PowerOperations.POW_OPERATION -> power(left, right)
else -> super.rightSideNumberOperation(operation, left, right)
@ -155,7 +163,7 @@ object FloatField : ExtendedField<Float>, Norm<Float, Float> {
}
/**
* A field for [Int] without boxing. Does not produce corresponding field element
* A field for [Int] without boxing. Does not produce corresponding ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object IntRing : Ring<Int>, Norm<Int, Int> {
@ -179,7 +187,7 @@ object IntRing : Ring<Int>, Norm<Int, Int> {
}
/**
* A field for [Short] without boxing. Does not produce appropriate field element
* A field for [Short] without boxing. Does not produce appropriate ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object ShortRing : Ring<Short>, Norm<Short, Short> {
@ -203,7 +211,7 @@ object ShortRing : Ring<Short>, Norm<Short, Short> {
}
/**
* A field for [Byte] values
* A field for [Byte] without boxing. Does not produce appropriate ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object ByteRing : Ring<Byte>, Norm<Byte, Byte> {
@ -227,7 +235,7 @@ object ByteRing : Ring<Byte>, Norm<Byte, Byte> {
}
/**
* A field for [Long] values
* A field for [Double] without boxing. Does not produce appropriate ring element.
*/
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
object LongRing : Ring<Long>, Norm<Long, Long> {

View File

@ -6,7 +6,7 @@ package scientifik.kmath.operations
* The operations are not exposed to class directly to avoid method bloat but instead are declared in the field.
* It also allows to override behavior for optional operations.
*/
interface TrigonometricOperations<T> : FieldOperations<T> {
interface TrigonometricOperations<T> : Algebra<T> {
/**
* Computes the sine of [arg].
*/
@ -62,6 +62,7 @@ interface TrigonometricOperations<T> : FieldOperations<T> {
* The identifier of inverse cosine.
*/
const val ACOS_OPERATION = "acos"
/**
* The identifier of inverse tangent.
*/
@ -106,7 +107,7 @@ fun <T : MathElement<out TrigonometricOperations<T>>> atan(arg: T): T = arg.cont
* The operations are not exposed to class directly to avoid method bloat but instead are declared in the field. It
* also allows to override behavior for optional operations.
*/
interface HyperbolicTrigonometricOperations<T> : FieldOperations<T> {
interface HyperbolicOperations<T> : Algebra<T> {
/**
* Computes the hyperbolic sine of [arg].
*/
@ -138,21 +139,67 @@ interface HyperbolicTrigonometricOperations<T> : FieldOperations<T> {
fun atanh(arg: T): T
companion object {
/**
* The identifier of hyperbolic sine.
*/
const val SINH_OPERATION = "sinh"
/**
* The identifier of hyperbolic cosine.
*/
const val COSH_OPERATION = "cosh"
/**
* The identifier of hyperbolic tangent.
*/
const val TANH_OPERATION = "tanh"
/**
* The identifier of inverse hyperbolic sine.
*/
const val ASINH_OPERATION = "asinh"
/**
* The identifier of inverse hyperbolic cosine.
*/
const val ACOSH_OPERATION = "acosh"
/**
* The identifier of inverse hyperbolic tangent.
*/
const val ATANH_OPERATION = "atanh"
}
}
fun <T : MathElement<out HyperbolicTrigonometricOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
fun <T : MathElement<out HyperbolicTrigonometricOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
fun <T : MathElement<out HyperbolicTrigonometricOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
fun <T : MathElement<out HyperbolicTrigonometricOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
fun <T : MathElement<out HyperbolicTrigonometricOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
fun <T : MathElement<out HyperbolicTrigonometricOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
/**
* Computes the hyperbolic sine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> sinh(arg: T): T = arg.context.sinh(arg)
/**
* Computes the hyperbolic cosine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> cosh(arg: T): T = arg.context.cosh(arg)
/**
* Computes the hyperbolic tangent of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> tanh(arg: T): T = arg.context.tanh(arg)
/**
* Computes the inverse hyperbolic sine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> asinh(arg: T): T = arg.context.asinh(arg)
/**
* Computes the inverse hyperbolic cosine of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> acosh(arg: T): T = arg.context.acosh(arg)
/**
* Computes the inverse hyperbolic tangent of [arg].
*/
fun <T : MathElement<out HyperbolicOperations<T>>> atanh(arg: T): T = arg.context.atanh(arg)
/**
* A context extension to include power operations based on exponentiation.