A comprehensive Scala 3 library providing high-precision mathematical number types including rational numbers, complex numbers, and quaternions with support for arbitrary precision arithmetic.
The numbers
library extends Scala's numeric ecosystem with mathematical types that maintain precision and provide exact arithmetic operations. It supports cross-compilation for JVM, JavaScript, and Native platforms, making it suitable for scientific computing, financial calculations, and any application requiring precise mathematical operations.
Key features include:
- Rational Numbers: Exact fraction arithmetic with automatic reduction
- Complex Numbers: Full complex arithmetic with multiple precision levels
- Quaternions: 4D number system for 3D rotations and advanced mathematics
- Arbitrary Precision: BigDecimal-based types for unlimited precision
- Functional Integration: Scala standard library integration via Fractional typeclasses
- Cross-Platform: JVM, JavaScript, and Native support
Add the following to your build.sbt
:
libraryDependencies += "io.github.edadma" %%% "numbers" % "0.0.1"
import io.github.edadma.numbers._
// Create rational numbers
val half = Rational(1, 2)
val third = Rational(1, 3)
// Exact arithmetic
val sum = half + third // 5/6
val product = half * third // 1/6
val power = half ^ 3 // 1/8
// Automatic reduction
val reduced = Rational(4, 8) // 1/2
// Convert to decimal
val decimal = half.doubleValue // 0.5
import io.github.edadma.numbers._
// Double precision complex numbers
val z1 = ComplexDouble(3, 4)
val z2 = ComplexDouble(1, 2)
val sum = z1 + z2 // 4+6i
val product = z1 * z2 // -5+10i
val conjugate = z1.conj // 3-4i
val magnitude = z1.abs // 5.0
// Mathematical functions
val exponential = z1.exp
val logarithm = z1.ln
val sine = z1.sin
// Rational coefficient complex numbers
val zr = ComplexRational(Rational(1,2), Rational(1,3))
// Arbitrary precision complex numbers
import BigDecimalMath.decimal128._
val zbd = ComplexBigDecimal(BigDecimal("1.23456789"), BigDecimal("2.98765432"))
import io.github.edadma.numbers._
// Create quaternions (a + bi + cj + dk)
val q1 = QuaternionDouble(1, 2, 3, 4)
val q2 = QuaternionDouble(2, 1, 0, 1)
// Quaternion arithmetic
val sum = q1 + q2
val product = q1 * q2 // Non-commutative multiplication
val conjugate = q1.conj // 1-2i-3j-4k
val norm = q1.abs
// Unit quaternions
val i = QuaternionDouble.i // 0+1i+0j+0k
val j = QuaternionDouble.j // 0+0i+1j+0k
val k = QuaternionDouble.k // 0+0i+0j+1k
// Rational quaternions for exact arithmetic
val qr = QuaternionRational(Rational(1,2), Rational(1,3), Rational(1,4), Rational(1,5))
import io.github.edadma.numbers._
import BigDecimalMath.decimal128._
// High-precision mathematical constants
val pi = bdmath.Pi.v
val e = bdmath.E.v
// High-precision functions
val sqrt2 = BigDecimalMath.sqrt(BigDecimal(2))
val ln10 = BigDecimalMath.ln(BigDecimal(10))
val sin30 = BigDecimalMath.sin(pi / 6)
// Complex arithmetic with arbitrary precision
val z = ComplexBigDecimal(pi, e)
val result = z.exp
Rational(numerator, denominator)
: Create a rational number+
,-
,*
,/
: Basic arithmetic operations^(Int)
,^(BigInt)
: Power operationsinv
: Multiplicative inverseabs
: Absolute valuefloor
,ceil
: Rounding operations
Available in multiple precision levels:
ComplexInt
: Integer coefficientsComplexDouble
: Double precisionComplexRational
: Rational coefficientsComplexBigInt
: BigInt coefficientsComplexBigDecimal
: Arbitrary precision
Operations:
+
,-
,*
,/
: Complex arithmeticconj
: Complex conjugateabs
: Magnitudearg
: Argument (phase angle)exp
,ln
,sqrt
: Exponential functionssin
,cos
,tan
: Trigonometric functionssinh
,cosh
,tanh
: Hyperbolic functions
Available in multiple precision levels:
QuaternionInt
: Integer coefficientsQuaternionDouble
: Double precisionQuaternionRational
: Rational coefficientsQuaternionBigInt
: BigInt coefficientsQuaternionBigDecimal
: Arbitrary precision
Operations:
+
,-
,*
: Quaternion arithmetic (multiplication is non-commutative)conj
: Quaternion conjugateabs
: Magnitudeinverse
: Multiplicative inverseexp
,ln
: Exponential functions
import BigDecimalMath._
// Use different precision contexts
object decimal64 {
implicit val bdmath = new BigDecimalMath(16) // 16 decimal places
}
object decimal256 {
implicit val bdmath = new BigDecimalMath(77) // 77 decimal places
}
The library provides Fractional
typeclass instances for seamless integration:
import io.github.edadma.numbers._
import ComplexDoubleIsFractional._
val complexNumbers = List(ComplexDouble(1,0), ComplexDouble(2,0), ComplexDouble(3,0))
val sum = complexNumbers.sum // ComplexDouble(6,0)
val product = complexNumbers.product // ComplexDouble(6,0)
val rationals = List(Rational(1,2), Rational(1,3), Rational(1,6))
val rationalSum = rationals.sum // Rational(1,1)
import io.github.edadma.numbers._
// Mandelbrot set iteration
def mandelbrot(c: ComplexDouble, maxIter: Int = 100): Int = {
var z = ComplexDouble.zero
var n = 0
while (z.abs <= 2.0 && n < maxIter) {
z = z * z + c
n += 1
}
n
}
val point = ComplexDouble(-0.75, 0.1)
val iterations = mandelbrot(point)
import io.github.edadma.numbers._
// Rotation quaternion for 90° around Z-axis
val angle = math.Pi / 4 // 45° in radians, but quaternion uses half-angle
val axis = QuaternionDouble(0, 0, 0, 1) // Z-axis
val rotation = QuaternionDouble(math.cos(angle), 0, 0, math.sin(angle))
// Apply rotation to a point
val point = QuaternionDouble(0, 1, 0, 0) // Point on X-axis
val rotated = rotation * point * rotation.conj
import io.github.edadma.numbers._
// Exact monetary calculations with rational numbers
val price = Rational(1299, 100) // $12.99
val taxRate = Rational(875, 10000) // 8.75% tax
val quantity = 3
val subtotal = price * quantity // $38.97 exactly
val tax = subtotal * taxRate // Exact tax calculation
val total = subtotal + tax // Exact total
println(s"Subtotal: $$${subtotal.doubleValue}")
println(s"Tax: $$${tax.doubleValue}")
println(s"Total: $$${total.doubleValue}")
The library includes comprehensive tests covering:
- Basic arithmetic operations for all number types
- Mathematical function accuracy
- Precision maintenance in calculations
- Edge cases and special values
- Integration with Scala standard library
Run tests with:
sbt test
For cross-platform testing:
sbt "project numbersJVM" test
sbt "project numbersJS" test
sbt "project numbersNative" test
- Rational arithmetic: Slower than floating-point but provides exact results
- BigDecimal types: Configurable precision with corresponding performance trade-offs
- Complex/Quaternion operations: Optimized implementations with lazy evaluation where beneficial
- Memory usage: Consider precision requirements vs. memory constraints for BigDecimal types
This project welcomes contributions from the community. Contributions are accepted using GitHub pull requests.
For a good pull request, please provide:
- Clear description: Include the basic "what" and "why" for the request
- Passing tests: Ensure all existing tests pass and add tests for new features
- Test coverage: Run
sbt coverage test coverageReport
to verify coverage - Documentation: Update README.md for new features or API changes
- Code style: Run
sbt scalafmtAll
to ensure consistent formatting
git clone https://github.com/edadma/numbers.git
cd numbers
sbt compile
sbt test
This project is licensed under the ISC License - see the LICENSE file for details.