package math
- Alphabetic
- By Inheritance
- math
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
- case class Above [A] extends Interval[A] with Product with Serializable
-
final
class
Algebraic
extends ScalaNumber with ScalaNumericConversions with Serializable
Algebraic provides an exact number type for algebraic numbers.
Algebraic provides an exact number type for algebraic numbers. Algebraic numbers are roots of polynomials with rational coefficients. With it, we can represent expressions involving addition, multiplication, division, n-roots (eg.
sqrt
orcbrt
), and roots of rational polynomials. So, it is similar Rational, but adds roots as a valid, exact operation. The cost is that this will not be as fast as Rational for many operations.In general, you can assume all operations on this number type are exact, except for those that explicitly construct approximations to an Algebraic number, such as
toBigDecimal
.For an overview of the ideas, algorithms, and proofs of this number type, you can read the following papers:
- "On Guaranteed Accuracy Computation." C. K. Yap.
- "Recent Progress in Exact Geometric Computation." C. Li, S. Pion, and C. K. Yap.
- "A New Constructive Root Bound for Algebraic Expressions" by C. Li & C. K. Yap.
- "A Separation Bound for Real Algebraic Expressions." C. Burnikel, et al.
- Annotations
- @SerialVersionUID()
-
class
AlgebraicAlgebra
extends AlgebraicIsFieldWithNRoot with AlgebraicIsReal with Serializable
- Annotations
- @SerialVersionUID()
- trait AlgebraicInstances extends AnyRef
- case class All [A] extends Interval[A] with Product with Serializable
- case class Below [A] extends Interval[A] with Product with Serializable
-
abstract
class
BinaryMerge
extends AnyRef
Abstract class that can be used to implement custom binary merges with e.g.
Abstract class that can be used to implement custom binary merges with e.g. special collision behavior or an ordering that is not defined via an Order[T] typeclass
- trait BitString [A] extends Bool[A]
- case class Bounded [A] extends Interval[A] with Product with Serializable
-
final
case class
Complex
[T](real: T, imag: T) extends ScalaNumber with ScalaNumericConversions with Serializable with Product
- Annotations
- @SerialVersionUID()
- trait ComplexInstances extends ComplexInstances1
- trait ComplexInstances0 extends AnyRef
- trait ComplexInstances1 extends ComplexInstances0
-
class
ComplexIsNumeric
[A] extends ComplexEq[A] with ComplexIsField[A] with Numeric[Complex[A]] with ComplexIsTrig[A] with ComplexIsNRoot[A] with ConvertableFromComplex[A] with ConvertableToComplex[A] with Order[Complex[A]] with ComplexIsSigned[A] with Serializable
- Annotations
- @SerialVersionUID()
- trait ConvertableFrom [A] extends Any
- trait ConvertableTo [A] extends Any
- case class Empty [A] extends Interval[A] with Product with Serializable
-
final
class
FloatComplex
extends AnyVal
Value class which encodes two floating point values in a Long.
Value class which encodes two floating point values in a Long.
We get (basically) unboxed complex numbers using this hack. The underlying implementation lives in the FastComplex object.
-
final
class
FpFilter
[A] extends AnyRef
A Floating-point Filter [1] provides a
Numeric
type that wraps anotherNumeric
type, but defers its computation, instead providing a floating point (Double
) approximation.A Floating-point Filter [1] provides a
Numeric
type that wraps anotherNumeric
type, but defers its computation, instead providing a floating point (Double
) approximation. For some operations, likesignum
, comparisons, equality checks, toFloat, etc, theDouble
approximation may be used to compute the result, rather than having to compute the exact value.An
FpFilter
can generally be used with any Ring numeric type (also supports EuclideanRing, Field, and NRoot). However, it should be kept in mind thatFpFilter
knows nothing about the type its wrapping and assumes that, generally, it is more accurate than it is. When anFpFilter
cannot determine an answer to some predicate exactly, it will defer to the wrapped value, so it probably doesn't make sense to wrapInt
s, when anInt
will overflow before aDouble
!Good candidates to wrap in
FpFilter
are BigInts, Rationals, BigDecimals, and Algebraic. Note that while Algebraic has an internal floating-point filter, this still provides benefits. Namely, the operator-fusion and allocation removal provided by the macros can make for much faster hot paths.Note: Both equals and hashCode will generally force the exact computation. They should be avoided (prefer
===
for equals)... otherwise why use bother?[1] Burnikel, Funke, Seel. Exact Geometric Computation Using Cascading. SoCG 1998.
- final class FpFilterApprox [A] extends AnyVal
- final class FpFilterExact [A] extends AnyVal
- trait Fractional [A] extends Field[A] with NRoot[A] with Integral[A]
- trait HighBranchingMedianOf5 extends AnyRef
- trait Integral [A] extends EuclideanRing[A] with ConvertableFrom[A] with ConvertableTo[A] with IsReal[A]
- class IntegralOps [A] extends AnyRef
-
sealed abstract
class
Interval
[A] extends Serializable
Interval represents a set of values, usually numbers.
Interval represents a set of values, usually numbers.
Intervals have upper and lower bounds. Each bound can be one of four kinds:
* Closed: The boundary value is included in the interval. * Open: The boundary value is excluded from the interval. * Unbound: There is no boundary value. * Empty: The interval itself is empty.
When the underlying type of the interval supports it, intervals may be used in arithmetic. There are several possible interpretations of interval arithmetic: the interval can represent uncertainty about a single value (for instance, a quantity +/- tolerance in engineering) or it can represent all values in the interval simultaneously. In this implementation we have chosen to use the probabillistic interpretation.
One common pitfall with interval arithmetic is that many familiar algebraic relations do not hold. For instance, given two intervals a and b:
a == b does not imply a * a == a * b
Consider a = b = [-1, 1]. Since any number times itself is non-negative, a * a = [0, 1]. However, a * b = [-1, 1], since we may actually have a=1 and b=-1.
These situations will result in loss of precision (in the form of wider intervals). The result is not wrong per se, but less acccurate than it could be.
These intervals should not be used with floating point bounds, as proper rounding is not implemented. Generally, the JVM is not an easy platform to perform robust arithmetic, as the IEEE 754 rounding modes cannot be set.
-
final
case class
Jet
[T](real: T, infinitesimal: Array[T]) extends ScalaNumber with ScalaNumericConversions with Serializable with Product
- Annotations
- @SerialVersionUID()
-
case class
JetDim
(dimension: Int) extends Product with Serializable
Used to implicitly define the dimensionality of the Jet space.
Used to implicitly define the dimensionality of the Jet space.
- dimension
the number of dimensions.
- trait JetInstances extends AnyRef
-
trait
Merge
extends Any
Interface for a merging strategy object.
- trait MutatingMedianOf5 extends AnyRef
-
sealed abstract
class
Natural
extends ScalaNumber with ScalaNumericConversions with Serializable
- Annotations
- @SerialVersionUID()
-
class
NaturalAlgebra
extends NaturalIsRig with NaturalIsReal with Serializable
- Annotations
- @SerialVersionUID()
- trait NaturalInstances extends AnyRef
- sealed trait Number extends ScalaNumber with ScalaNumericConversions with Serializable
-
class
NumberAlgebra
extends NumberIsField with NumberIsNRoot with NumberIsTrig with NumberIsReal with Serializable
- Annotations
- @SerialVersionUID()
- trait NumberInstances extends AnyRef
-
trait
NumberTag
[A] extends AnyRef
A
NumberTag
provides information about important implementations details of numbers.A
NumberTag
provides information about important implementations details of numbers. For instance, it includes information about whether we can expect arithmetic to overflow or produce invalid values, the bounds of the number if they exist, whether it is an approximate or exact number type, etc. -
trait
Numeric
[A] extends Ring[A] with AdditiveAbGroup[A] with MultiplicativeAbGroup[A] with NRoot[A] with ConvertableFrom[A] with ConvertableTo[A] with IsReal[A]
TODO 3.
TODO 3. LiteralOps? Literal conversions? 4. Review operator symbols? 5. Support for more operators? 6. Start to worry about things like e.g. pow(BigInt, BigInt)
- case class Point [A] extends Interval[A] with Product with Serializable
- trait Polynomial [C] extends AnyRef
- trait PolynomialEq [C] extends Eq[Polynomial[C]]
- trait PolynomialEuclideanRing [C] extends PolynomialRing[C] with EuclideanRing[Polynomial[C]] with VectorSpace[Polynomial[C], C]
- trait PolynomialInstances extends PolynomialInstances3
- trait PolynomialInstances0 extends AnyRef
- trait PolynomialInstances1 extends PolynomialInstances0
- trait PolynomialInstances2 extends PolynomialInstances1
- trait PolynomialInstances3 extends PolynomialInstances2
- trait PolynomialRig [C] extends PolynomialSemiring[C] with Rig[Polynomial[C]]
- trait PolynomialRing [C] extends PolynomialRng[C] with Ring[Polynomial[C]]
- trait PolynomialRng [C] extends PolynomialSemiring[C] with RingAlgebra[Polynomial[C], C]
- trait PolynomialSemiring [C] extends Semiring[Polynomial[C]]
- final case class Quaternion [A](r: A, i: A, j: A, k: A) extends ScalaNumber with ScalaNumericConversions with Serializable with Product
- trait QuaternionInstances extends AnyRef
- sealed abstract class Rational extends ScalaNumber with ScalaNumericConversions with Ordered[Rational]
-
class
RationalAlgebra
extends RationalIsField with RationalIsReal with Serializable
- Annotations
- @SerialVersionUID()
- trait RationalInstances extends AnyRef
- sealed trait Real extends ScalaNumber with ScalaNumericConversions
-
class
RealAlgebra
extends RealIsFractional
- Annotations
- @SerialVersionUID()
- trait RealInstances extends AnyRef
- trait RealIsFractional extends Fractional[Real] with Order[Real] with Signed[Real] with Trig[Real]
-
sealed abstract
class
SafeLong
extends ScalaNumber with ScalaNumericConversions with Ordered[SafeLong]
Provides a type to do safe long arithmetic.
Provides a type to do safe long arithmetic. This type will never overflow, but rather convert the underlying long to a BigInteger as need and back down to a Long when possible.
- trait SafeLongInstances extends AnyRef
- trait Select extends Any
-
trait
SelectLike
extends Select
Given a function for finding approximate medians, this will create an exact median finder.
-
trait
Sort
extends Any
Interface for a sorting strategy object.
-
final
class
Trilean
extends AnyVal
Implementation of three-valued logic.
Implementation of three-valued logic.
This type resembles Boolean, but has three values instead of two:
- Trilean.True (equivalent to true)
- Trilean.False (equivalent to false)
- Trilean.Unknown
Trilean supports the same operations that Boolean does, and as long as all values are True or False, the results will be the same. However, the truth tables have to be extended to work with unknown:
not: -+- T|F U|U F|T
and: |T U F -+----- T|T U F U|U U F F|F F F
or: |T U F -+----- T|T T T U|T U U F|T U F
Trilean is implemented as a value type, so in most cases it will only have the overhead of a single Int. However, in some situations it will be boxed.
- class TrileanAlgebra extends Heyting[Trilean]
- final class UByte extends AnyVal with ScalaNumericAnyConversions
- trait UByteInstances extends AnyRef
- final class UInt extends AnyVal
- trait UIntInstances extends AnyRef
- final class ULong extends AnyVal
- trait ULongInstances extends AnyRef
- final class UShort extends AnyVal
- trait UShortInstances extends AnyRef
Value Members
- final def IEEEremainder(x: Double, d: Double): Double
- final def abs[A](a: A)(implicit ev: Signed[A]): A
- final def abs(n: Double): Double
- final def abs(n: Float): Float
- final def abs(n: Long): Long
- final def abs(n: Int): Int
- final def abs(n: Short): Short
-
final
def
abs(n: Byte): Byte
abs
- final def acos[A](a: A)(implicit ev: Trig[A]): A
- final def asin[A](a: A)(implicit ev: Trig[A]): A
- final def atan[A](a: A)(implicit ev: Trig[A]): A
- final def atan2[A](y: A, x: A)(implicit ev: Trig[A]): A
- final def cbrt(x: Double): Double
- final def ceil[A](a: A)(implicit ev: IsReal[A]): A
- final def ceil(n: BigDecimal): BigDecimal
- final def ceil(n: Double): Double
-
final
def
ceil(n: Float): Float
ceil
-
def
choose(n: Long, k: Long): BigInt
choose (binomial coefficient)
- final def copySign(m: Float, s: Float): Float
- final def copySign(m: Double, s: Double): Double
- final def cos[A](a: A)(implicit ev: Trig[A]): A
- final def cosh(x: Double): Double
- final def cosh[A](x: A)(implicit ev: Trig[A]): A
- final def e[A](implicit ev: Trig[A]): A
-
final
def
e: Double
e
- final def exp[A](a: A)(implicit t: Trig[A]): A
- final def exp(k: BigDecimal): BigDecimal
- final def exp(k: Int, precision: Int): BigDecimal
-
final
def
exp(n: Double): Double
exp
- final def expm1(x: Double): Double
-
def
fact(n: Long): BigInt
factorial
-
def
fib(n: Long): BigInt
fibonacci
- final def floor[A](a: A)(implicit ev: IsReal[A]): A
- final def floor(n: BigDecimal): BigDecimal
- final def floor(n: Double): Double
-
final
def
floor(n: Float): Float
floor
- final def gcd[A](x: A, y: A, z: A, rest: A*)(implicit ev: EuclideanRing[A]): A
- final def gcd[A](xs: Seq[A])(implicit ev: EuclideanRing[A]): A
- final def gcd[A](x: A, y: A)(implicit ev: EuclideanRing[A]): A
- final def gcd(a: BigInt, b: BigInt): BigInt
-
final
def
gcd(_x: Long, _y: Long): Long
gcd
- final def getExponent(x: Float): Int
- final def getExponent(x: Double): Int
- final def hypot[A](x: A, y: A)(implicit f: Field[A], n: NRoot[A], o: Order[A]): A
- final def lcm[A](x: A, y: A)(implicit ev: EuclideanRing[A]): A
- final def lcm(a: BigInt, b: BigInt): BigInt
-
final
def
lcm(x: Long, y: Long): Long
lcm
- final def log[A](a: A, base: Int)(implicit f: Field[A], t: Trig[A]): A
- final def log[A](a: A)(implicit t: Trig[A]): A
- def log(n: BigDecimal, base: Int): BigDecimal
- final def log(n: BigDecimal): BigDecimal
- final def log(n: Double, base: Int): Double
-
final
def
log(n: Double): Double
log
- final def log10(x: Double): Double
- final def log1p(x: Double): Double
- final def max[A](x: A, y: A)(implicit ev: Order[A]): A
- final def max(x: Double, y: Double): Double
- final def max(x: Float, y: Float): Float
- final def max(x: Long, y: Long): Long
- final def max(x: Int, y: Int): Int
- final def max(x: Short, y: Short): Short
-
final
def
max(x: Byte, y: Byte): Byte
max
- final def min[A](x: A, y: A)(implicit ev: Order[A]): A
- final def min(x: Double, y: Double): Double
- final def min(x: Float, y: Float): Float
- final def min(x: Long, y: Long): Long
- final def min(x: Int, y: Int): Int
- final def min(x: Short, y: Short): Short
-
final
def
min(x: Byte, y: Byte): Byte
min
- final def nextAfter(x: Float, y: Float): Float
- final def nextAfter(x: Double, y: Double): Double
- final def nextUp(x: Float): Float
- final def nextUp(x: Double): Double
- final def pi[A](implicit ev: Trig[A]): A
-
final
def
pi: Double
pi
- final def pow(base: Double, exponent: Double): Double
-
final
def
pow(base: Long, exponent: Long): Long
Exponentiation function, e.g.
Exponentiation function, e.g. x^y
If base^ex doesn't fit in a Long, the result will overflow (unlike Math.pow which will return +/- Infinity).
- final def pow(base: BigInt, ex: BigInt): BigInt
-
final
def
pow(base: BigDecimal, exponent: BigDecimal): BigDecimal
pow
- final def random(): Double
- final def rint(x: Double): Double
- final def round[A](a: A)(implicit ev: IsReal[A]): A
- final def round(a: BigDecimal): BigDecimal
- final def round(a: Double): Double
-
final
def
round(a: Float): Float
round
- final def scalb(d: Float, s: Int): Float
- final def scalb(d: Double, s: Int): Double
- final def signum[A](a: A)(implicit ev: Signed[A]): Int
- final def signum(x: Float): Float
-
final
def
signum(x: Double): Double
signum
- final def sin[A](a: A)(implicit ev: Trig[A]): A
- final def sinh[A](x: A)(implicit ev: Trig[A]): A
- final def sqrt[A](a: A)(implicit ev: NRoot[A]): A
-
final
def
sqrt(x: Double): Double
sqrt
- final def tan[A](a: A)(implicit ev: Trig[A]): A
- final def tanh[A](x: A)(implicit ev: Trig[A]): A
- final def toDegrees(a: Double): Double
- final def toRadians(a: Double): Double
- final def ulp(x: Float): Double
- final def ulp(x: Double): Double
- object Algebraic extends AlgebraicInstances with Serializable
-
object
BinaryMerge
extends Merge
Merge that uses binary search to reduce the number of comparisons
Merge that uses binary search to reduce the number of comparisons
This can be orders of magnitude quicker than a linear merge for types that have a relatively expensive comparison operation (e.g. Rational, BigInt, tuples) and will not be much slower than linear merge even in the worst case for types that have a very fast comparison (e.g. Int)
- object BitString
- object Complex extends ComplexInstances with Serializable
- object ConvertableFrom
- object ConvertableTo
-
object
FastComplex
FastComplex is an ugly, beautiful hack.
FastComplex is an ugly, beautiful hack.
The basic idea is to encode two 32-bit Floats into a single 64-bit Long. The lower-32 bits are the "real" Float and the upper-32 are the "imaginary" Float.
Since we're overloading the meaning of Long, all the operations have to be defined on the FastComplex object, meaning the syntax for using this is a bit ugly. To add to the ugly beauty of the whole thing I could imagine defining implicit operators on Long like +@, -@, *@, /@, etc.
You might wonder why it's even worth doing this. The answer is that when you need to allocate an array of e.g. 10-20 million complex numbers, the GC overhead of using *any* object is HUGE. Since we can't build our own "pass-by-value" types on the JVM we are stuck doing an encoding like this.
Here are some profiling numbers for summing an array of complex numbers, timed against a concrete case class implementation using Float (in ms):
size | encoded | class 1M | 5.1 | 5.8 5M | 28.5 | 91.7 10M | 67.7 | 828.1 20M | 228.0 | 2687.0
Not bad, eh?
- object FloatComplex
- object FpFilter
- object FpFilterApprox
- object FpFilterExact
- object Fractional
-
object
InsertionSort
extends Sort
Simple implementation of insertion sort.
Simple implementation of insertion sort.
Works for small arrays but due to O(n^2) complexity is not generally good.
- object Integral
- object Interval extends Serializable
-
object
Jet
extends JetInstances with Serializable
A simple implementation of N-dimensional dual numbers, for automatically computing exact derivatives of functions.
Overview
A simple implementation of N-dimensional dual numbers, for automatically computing exact derivatives of functions. This code (and documentation) closely follow the one in Google's "Ceres" library of non-linear least-squares solvers (see Sameer Agarwal, Keir Mierle, and others: Ceres Solver.)
While a complete treatment of the mechanics of automatic differentiation is beyond the scope of this header (see http://en.wikipedia.org/wiki/Automatic_differentiation for details), the basic idea is to extend normal arithmetic with an extra element "h" such that h != 0, but h2 = 0. Dual numbers are extensions of the real numbers analogous to complex numbers: whereas complex numbers augment the reals by introducing an imaginary unit i such that i2 = -1, dual numbers introduce an "infinitesimal" unit h such that h2 = 0. Analogously to a complex number c = x + y*i, a dual number d = x * y*h has two components: the "real" component x, and an "infinitesimal" component y. Surprisingly, this leads to a convenient method for computing exact derivatives without needing to manipulate complicated symbolic expressions.
For example, consider the function
f(x) = x * x ,
evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20. Next, augment 10 with an infinitesimal h to get:
f(10 + h) = (10 + h) * (10 + h) = 100 + 2 * 10 * h + h * h = 100 + 20 * h +--- +----- | | +--- This is zero | +----------------- This is df/dx
Note that the derivative of f with respect to x is simply the infinitesimal component of the value of f(x + h). So, in order to take the derivative of any function, it is only necessary to replace the numeric "object" used in the function with one extended with infinitesimals. The class Jet, defined in this header, is one such example of this, where substitution is done with generics.
To handle derivatives of functions taking multiple arguments, different infinitesimals are used, one for each variable to take the derivative of. For example, consider a scalar function of two scalar parameters x and y:
f(x, y) = x * x + x * y
Following the technique above, to compute the derivatives df/dx and df/dy for f(1, 3) involves doing two evaluations of f, the first time replacing x with x + h, the second time replacing y with y + h.
For df/dx:
f(1 + h, y) = (1 + h) * (1 + h) + (1 + h) * 3 = 1 + 2 * h + 3 + 3 * h = 4 + 5 * h Therefore df/dx = 5
For df/dy:
f(1, 3 + h) = 1 * 1 + 1 * (3 + h) = 1 + 3 + h = 4 + h Therefore df/dy = 1
To take the gradient of f with the implementation of dual numbers ("jets") in this file, it is necessary to create a single jet type which has components for the derivative in x and y, and pass them to a routine computing function f. It is convenient to use a generic version of f, that can be called also with non-jet numbers for standard evaluation:
def f[@specialized(Double) T : Field](x: T, y: T): T = x * x + x * y val xValue = 9.47892774 val yValue = 0.287740 // The "2" means there should be 2 dual number components. implicit val dimension = JetDim(2) val x: Jet[Double] = xValue + Jet.h[Double](0); // Pick the 0th dual number for x. val y: Jet[Double] = yValue + Jet.h[Double](1); // Pick the 1th dual number for y. val z: Jet[Double] = f(x, y); println("df/dx = " + z.infinitesimal(0) + ", df/dy = " + z.infinitesimal(1));
For the more mathematically inclined, this file implements first-order "jets". A 1st order jet is an element of the ring
T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2
which essentially means that each jet consists of a "scalar" value 'a' from T and a 1st order perturbation vector 'v' of length N:
x = a + \sum_i v[i] t_i
A shorthand is to write an element as x = a + u, where u is the perturbation. Then, the main point about the arithmetic of jets is that the product of perturbations is zero:
(a + u) * (b + v) = ab + av + bu + uv = ab + (av + bu) + 0
which is what operator* implements below. Addition is simpler:
(a + u) + (b + v) = (a + b) + (u + v).
The only remaining question is how to evaluate the function of a jet, for which we use the chain rule:
f(a + u) = f(a) + f'(a) u
where f'(a) is the (scalar) derivative of f at a.
By pushing these things through generics, we can write routines that at same time evaluate mathematical functions and compute their derivatives through automatic differentiation.
-
object
LinearMerge
extends Merge
Simple linear merge
- object LinearSelect extends SelectLike with HighBranchingMedianOf5
-
object
MergeSort
extends Sort
In-place merge sort implementation.
In-place merge sort implementation. This sort is stable but does mutate the given array. It is an in-place sort but it does allocate a temporary array of the same size as the input. It uses InsertionSort for sorting very small arrays.
- object Natural extends NaturalInstances with Serializable
-
object
Number
extends NumberInstances with Serializable
Convenient apply and implicits for Numbers
- object NumberTag
- object Numeric
-
object
Polynomial
extends PolynomialInstances
Polynomial A univariate polynomial class and EuclideanRing extension trait for arithmetic operations.
Polynomial A univariate polynomial class and EuclideanRing extension trait for arithmetic operations. Polynomials can be instantiated using any type C for which a Ring[C] and Signed[C] are in scope, with exponents given by Int values. Some operations require a Field[C] to be in scope.
- object Quaternion extends QuaternionInstances with Serializable
- object QuickSelect extends SelectLike with HighBranchingMedianOf5
-
object
QuickSort
In-place quicksort implementation.
In-place quicksort implementation. It is not stable, but does not allocate extra space (other than stack). Like MergeSort, it uses InsertionSort for sorting very small arrays.
- object Rational extends RationalInstances with Serializable
- object Real extends RealInstances with Serializable
- object SafeLong extends SafeLongInstances with Serializable
- object Searching
- object Selection
-
object
Sorting
Object providing in-place sorting capability for arrays.
Object providing in-place sorting capability for arrays.
Sorting.sort() uses quickSort() by default (in-place, not stable, generally fastest but might hit bad cases where it's O(n^2)). Also provides mergeSort() (in-place, stable, uses extra memory, still pretty fast) and insertionSort(), which is slow except for small arrays.
- object Trilean
- object UByte extends UByteInstances
- object UInt extends UIntInstances
- object ULong extends ULongInstances
- object UShort extends UShortInstances