// Copyright 2025 International Digital Economy Academy
//
// 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.
///|
/// Rational number type.
///
/// Invariants:
/// - The denominator is always positive.
/// - The numerator and denominator are always coprime.
struct Rational[T] {
numerator : T
denominator : T
} derive(Eq)
///|
/// Returns the numerator of this rational number.
pub fn[T] Rational::numerator(self : Rational[T]) -> T {
self.numerator
}
///|
/// Returns the denominator of this rational number.
pub fn[T] Rational::denominator(self : Rational[T]) -> T {
self.denominator
}
///|
trait Integral: Add + Sub + Mul + Div + Neg + Mod + Show + Eq + Compare + @quickcheck.Arbitrary {
fn from_int(Int) -> Self
fn signum(self : Self) -> Int
fn abs(self : Self) -> Self
fn to_bigint(self : Self) -> BigInt
fn from_bigint(BigInt) -> Self?
fn compare_fraction(Self, Self, Self, Self) -> Int
}
///|
pub impl Integral for Int64 with fn from_int(i : Int) -> Int64 {
i.to_int64()
}
///|
pub impl Integral for Int64 with fn abs(self : Int64) -> Int64 {
self.abs()
}
///|
pub impl Integral for Int64 with fn signum(self : Int64) -> Int {
self.compare(0L)
}
///|
pub impl Integral for Int64 with fn to_bigint(self : Int64) -> BigInt {
BigInt::from_int64(self)
}
///|
pub impl Integral for Int64 with fn from_bigint(b : BigInt) -> Int64? {
if b.compare_int64(@int64.MIN_VALUE) >= 0 &&
b.compare_int64(@int64.MAX_VALUE) <= 0 {
Some(b.to_int64())
} else {
None
}
}
///|
pub impl Integral for Int with fn from_int(i : Int) -> Int {
i
}
///|
pub impl Integral for Int with fn abs(self : Int) -> Int {
self.abs()
}
///|
pub impl Integral for Int with fn signum(self : Int) -> Int {
self.compare(0)
}
///|
pub impl Integral for Int with fn to_bigint(self : Int) -> BigInt {
BigInt::from_int(self)
}
///|
pub impl Integral for Int with fn from_bigint(b : BigInt) -> Int? {
if b.compare_int(@int.MIN_VALUE) >= 0 && b.compare_int(@int.MAX_VALUE) <= 0 {
Some(b.to_int())
} else {
None
}
}
///|
pub impl Integral for BigInt with fn from_int(i : Int) -> BigInt {
BigInt::from_int(i)
}
///|
pub impl Integral for BigInt with fn abs(self : BigInt) -> BigInt {
if self < 0N {
-self
} else {
self
}
}
///|
pub impl Integral for BigInt with fn signum(self : BigInt) -> Int {
self.compare(0N)
}
///|
pub impl Integral for BigInt with fn to_bigint(self : BigInt) -> BigInt {
self
}
///|
pub impl Integral for BigInt with fn from_bigint(b : BigInt) -> BigInt? {
Some(b)
}
///|
pub type Rational64 = Rational[Int64]
///|
pub type Rational32 = Rational[Int]
///|
pub type BigRational = Rational[BigInt]
///|
#deprecated
pub extend Rational with Eq::{not_equal, equal}