std/number/lib
std/number/src/lib.trb
Every numeric type of the language: Numeric, Signed, Bits and Real, the traits their operators go through;
the sized integer types and the two floating-point types; Decimal; the conversions between all of them; and
ByteSize, a number of bytes in its units.
Reach for Int, UInt or Float - the three default-width aliases - and only name a sized type (Int8,
UInt32, ...) where a signature has to say exactly how wide a value is.
trait Numeric
trait Numeric with Add, Subtract, Multiply, Divide, Remainder, Equals, Compare, Show, TryFrom<String, NumberParseError>
The arithmetic and comparison every number has: +, -, *, /, %, ==, <, reading one from text, and its
zero and its one.
Text is a source like any other, so Int.tryFrom("42") is the conversion and there is no parse beside it.
Examples
fn total<Scalar: Numeric>(values: List<Scalar>): Scalar {
var sum = Scalar.zero
for value in values {
sum = sum + value
}
sum
}
print total([1, 2, 3])
print total([0.5, 0.25])
const zero
static zero: Self
Zero of this type: what a sum starts from, and what a generic body compares against. Scalar.zero reads it
through a type parameter, Int.zero and Float.zero through the type.
const one
static one: Self
One of this type: what a product starts from, and the unit of an identity matrix or a homogeneous coordinate.
trait Signed
trait Signed with Numeric, Negate
Numeric plus a sign: the unary - and Signed.absolute. What every signed number has beyond an unsigned one.
fn absolute
fn absolute(): Self
The value without its sign.
trait Real
trait Real with Signed, Power, Power<Int64>
Signed plus the operations that need a root or an angle: the scalar of geometry, trigonometry and interpolation.
It is the bound that separates what a vector can do with whole numbers from what it needs a continuous scalar for.
lengthSquared and dot are arithmetic and live under Numeric; length, normalized, rotated and every angle
need a Real. A library that is generic over the scalar therefore says which half it is in by its bound alone, and a
grid vector never accidentally gets a square root.
Two types carry it. Float64 is the fast one and answers whatever the platform's mathematics library answers.
Fixed (std/linear) is the deterministic one: every operation is integer arithmetic, so it answers the same bits on
every platform and out of every back end, which is what lockstep simulation and a replay need.
Angles are in radians throughout, and std/linear's Angle is the wrapper that keeps degrees from being passed as
radians.
Examples
fn hypotenuse<Scalar: Real>(first: Scalar, second: Scalar): Scalar {
(first * first + second * second).squareRoot()
}
print hypotenuse(3.0, 4.0)
Pitfalls
- The results are not bit-identical between implementors, and for
Float64not even between platforms:sineis whatever the platform's mathematics library computes. Where the last bit has to agree - a lockstep simulation, a replay, a checksum over a world state - the scalar isFixedand notFloat.
Open
Float32does not carry it yet. It has its arithmetic,compare,Showand the narrowing from aFloat64, but none of the operations of a root or an angle:<math.h>has thefloatfunctions (sqrtf,sinf,powf, ...), andRealof aFloat32is oneextendover them.
Related
const pi
static pi: Self
Half a turn in radians - the ratio of a circle's circumference to its diameter - in this scalar's type:
Scalar.pi in a body that is generic over it, whose literals could not write the digits.
const tau
static tau: Self
A whole turn in radians, twice Real.pi, rounded once in this scalar's type rather than doubled.
const e
static e: Self
The base of the natural logarithm, in this scalar's type: Scalar.e, named like Real.pi.
const epsilon
static epsilon: Self
The gap between one and the next value this scalar can hold: the resolution a tolerance cannot go below. It is the machine epsilon of a float and the one part of a fixed-point number.
fn squareRoot
fn squareRoot(): Self
The non-negative square root. Negative input answers a value the implementor documents.
fn sine
fn sine(): Self
The sine of an angle in radians.
fn cosine
fn cosine(): Self
The cosine of an angle in radians.
fn tangent
fn tangent(): Self
The tangent of an angle in radians.
fn arcSine
fn arcSine(): Self
The angle in radians whose sine is this value, in [-pi/2, pi/2].
Panics
Outside [-1, 1], where no angle has this sine. The precondition is an ordinary expression,
value.absolute() <= Scalar.one, so a value outside is a broken promise of the program and every implementor stops
there rather than answering a number (docs/design/PANICS.md, 5.1). value.clamp(-Scalar.one, Scalar.one) first
is the total form, for a ratio that rounding pushed a hair past one.
fn arcCosine
fn arcCosine(): Self
The angle in radians whose cosine is this value, in [0, pi].
Panics
Outside [-1, 1], as Real.arcSine says.
fn arcTangent
fn arcTangent(): Self
The angle in radians whose tangent is this value, in (-pi/2, pi/2).
fn arcTangentDivided
fn arcTangentDivided(by: Self): Self
The angle in radians of the point (by, self), in (-pi, pi]: the arc tangent of self / by that uses the sign
of both to pick the quadrant. This is what turns a vector into a direction, and it is why it takes a label -
y.arcTangentDivided(by: x) says which of the two is which, where a bare pair of arguments does not.
fn exponential
fn exponential(): Self
Real.e raised to this value: Scalar.e ** value, without a logarithm of e in between.
fn naturalLogarithm
fn naturalLogarithm(): Self
The logarithm to the base Real.e. Zero and a negative value answer what the implementor documents.
fn logarithm
fn logarithm(base: Self): Self
The logarithm to another base: (8.0).logarithm(base: 2.0) is 3.0. It is the natural logarithm of the value
over the one of the base, so an implementor that has a faster way overrides it.
fn floor
fn floor(): Self
Rounded towards negative infinity.
fn ceiling
fn ceiling(): Self
Rounded towards positive infinity.
fn round
fn round(): Self
Rounded to the nearest whole value, halves away from zero.
fn halved
fn halved(): Self
Half the value. It is a member and not value / 2 at the call, because a body that is generic over the scalar
cannot write the literal 2 at all: a literal has a type, and inside such a body that type is the parameter.
Halving is what a midpoint, a radius and an average are made of, so the trait carries it.
fn doubled
fn doubled(): Self
Twice the value.
fn radiansOfDegrees
fn radiansOfDegrees(): Self
The angle in radians that this many degrees is.
Degrees are a member of the scalar and not a function of std/linear, because the conversion needs the value of
pi in this scalar's type - and a body that is generic over the scalar can write neither pi nor 180. Each
implementor carries its own exact factor.
fn degreesOfRadians
fn degreesOfRadians(): Self
The angle in degrees that this many radians is.
trait Bits
trait Bits
The bit operations of an integer, and the operators that are them: a & b is bitwiseAnd, a | b bitwiseOr,
a ^ b bitwiseExclusiveOr, ~a bitwiseNot, a << n shiftedLeft(by:) and a >> n shiftedRight(by:).
const value = 0x1234
const low = value & 0xFF
const mixed = (value ^ low) << 5
print "{low} {mixed}"
The operators sit where Go and Swift put them, so there is no C trap: & binds like *, | and ^ like +, a
shift between * and ** - and flags & 1 == 0 is (flags & 1) == 0.
The shift of a signed type is arithmetic (it keeps the sign), the shift of an unsigned type is logical, and the bits that leave the width are dropped. A shift by a negative amount or by the width of the type or more panics, like every other operation that leaves its range.
fn bitwiseAnd
fn bitwiseAnd(other: Self): Self
Bit-for-bit and. This is &.
fn bitwiseOr
fn bitwiseOr(other: Self): Self
Bit-for-bit or. This is |.
fn bitwiseExclusiveOr
fn bitwiseExclusiveOr(other: Self): Self
Bit-for-bit exclusive or. This is ^.
fn bitwiseNot
fn bitwiseNot(): Self
Every bit flipped. This is the prefix ~.
fn shiftedLeft
fn shiftedLeft(by: Int64): Self
Shifted towards the high bits. This is <<.
fn shiftedRight
fn shiftedRight(by: Int64): Self
Shifted towards the low bits: arithmetic for a signed type, logical for an unsigned one. This is >>.
trait Integer
trait Integer with Numeric
Numeric of a whole number, with its range: Integer.minimum, Integer.maximum, and the arithmetic that answers
None exactly where the operator would panic.
a + b panics on overflow in every profile, because a wrong number is worse than a stop. The members here are its
total twins (CONCEPT.md, "Error Handling"): a.addedChecked(b) is a + b where that fits the type and None
where it does not, and so on for -, *, / and % - the division and the remainder also answer None for a
zero divisor and for the smallest value of a signed type divided by -1. They cost a comparison or two in front of
the operation, which cannot overflow any more then.
Examples
const total: Int8 = 100
print total.addedChecked(27)
print total.addedChecked(28)
print(Int.maximum.multipliedChecked(2) ?? 0)
Related
UInt64.addedWrapping- the arithmetic that wraps around, for the one case that needs it: hashing.
const minimum
static minimum: Self
The smallest value of the type.
const maximum
static maximum: Self
The largest value of the type.
fn addedChecked
fn addedChecked(other: Self): Self?
self + other, or None where the sum does not fit the type.
fn subtractedChecked
fn subtractedChecked(other: Self): Self?
self - other, or None where the difference does not fit the type.
fn multipliedChecked
fn multipliedChecked(other: Self): Self?
self * other, or None where the product does not fit the type.
fn dividedChecked
fn dividedChecked(other: Self): Self?
self / other, or None for a zero divisor and for the smallest value of a signed type divided by -1.
fn remainderChecked
fn remainderChecked(other: Self): Self?
self % other, or None where self / other would be None as well.
type NumberParseError
type NumberParseError with Error
What Int.tryFrom(text) fails with: the text is not a valid number.
field text
text: String
The text that does not describe a number. Every conversion that fails with it names its parameter text, which is
what lets a back end build the failure without knowing anything about this type (docs/BACKEND.md, "the parameter of
the same name").
type NumberRangeError
type NumberRangeError with Error
What a narrowing conversion (Int8.tryFrom, Int64.tryFrom) fails with: the value does not fit the target type.
field message
message: String
What went out of range.
type Int8
native type Int8 with Signed, Hash, Bits, Power<Int64>
An 8-bit signed integer, from Int8.minimum to Int8.maximum.
type Int16
native type Int16 with Signed, Hash, Bits, Power<Int64>
A 16-bit signed integer, from Int16.minimum to Int16.maximum.
type Int32
native type Int32 with Signed, Hash, Bits, Power<Int64>
A 32-bit signed integer, from Int32.minimum to Int32.maximum.
type Int64
native type Int64 with Signed, Hash, Bits, Power<Int64>
A 64-bit signed integer, and the type of an integer literal.
type UInt8
native type UInt8 with Numeric, Hash, Bits, Power<Int64>
An 8-bit unsigned integer, from 0 to UInt8.maximum.
type UInt16
native type UInt16 with Numeric, Hash, Bits, Power<Int64>
A 16-bit unsigned integer, from 0 to UInt16.maximum.
type UInt32
native type UInt32 with Numeric, Hash, Bits, Power<Int64>
A 32-bit unsigned integer, from 0 to UInt32.maximum.
type UInt64
native type UInt64 with Numeric, Hash, Bits, Power<Int64>
A 64-bit unsigned integer, from 0 to UInt64.maximum.
extend Int8
extend Int8
The range of an Int8, and its zero and one.
const zero
static zero: Self = 0
Zero, the Numeric.zero of an Int8.
const one
static one: Self = 1
One, the Numeric.one of an Int8.
const minimum
static minimum: Self = -128
The smallest Int8.
const maximum
static maximum: Self = 127
The largest Int8.
extend Int16
extend Int16
The range of an Int16, and its zero and one.
const zero
static zero: Self = 0
Zero, the Numeric.zero of an Int16.
const one
static one: Self = 1
One, the Numeric.one of an Int16.
const minimum
static minimum: Self = -32768
The smallest Int16.
const maximum
static maximum: Self = 32767
The largest Int16.
extend Int32
extend Int32
The range of an Int32, and its zero and one.
const zero
static zero: Self = 0
Zero, the Numeric.zero of an Int32.
const one
static one: Self = 1
One, the Numeric.one of an Int32.
const minimum
static minimum: Self = -2147483648
The smallest Int32.
const maximum
static maximum: Self = 2147483647
The largest Int32.
extend UInt8
extend UInt8
The range of a UInt8, and its zero and one.
const zero
static zero: Self = 0
Zero, the Numeric.zero of a UInt8.
const one
static one: Self = 1
One, the Numeric.one of a UInt8.
const minimum
static minimum: Self = 0
Always 0.
const maximum
static maximum: Self = 255
The largest UInt8.
extend UInt16
extend UInt16
The range of a UInt16, and its zero and one.
const zero
static zero: Self = 0
Zero, the Numeric.zero of a UInt16.
const one
static one: Self = 1
One, the Numeric.one of a UInt16.
const minimum
static minimum: Self = 0
Always 0.
const maximum
static maximum: Self = 65535
The largest UInt16.
extend UInt32
extend UInt32
The range of a UInt32, and its zero and one.
const zero
static zero: Self = 0
Zero, the Numeric.zero of a UInt32.
const one
static one: Self = 1
One, the Numeric.one of a UInt32.
const minimum
static minimum: Self = 0
Always 0.
const maximum
static maximum: Self = 4294967295
The largest UInt32.
type Float32
native type Float32 with Signed
A 32-bit floating-point number: IEEE-754 binary32, rounded to the nearest one with ties to even after every operation, in both back ends and in a folded constant alike.
A decimal literal of a Float32 is read as a Float64 and rounded from there, which is also how
Float32.tryFrom(String) reads a text, and Show writes the shortest text that reads back into the same bits:
0.1 + 0.2 is 0.3 here, where a Float64 shows 0.30000000000000004. compare is the total order of
Float64's, with nan above everything.
extend Float32
extend Float32
The zero and the one of a Float32, its two infinities, and the one value for which == is never true.
const zero
static zero: Self = 0.0
Zero, the Numeric.zero of an Float32.
const one
static one: Self = 1.0
One, the Numeric.one of an Float32.
const nan
static nan: Self = 0.0 / 0.0
"Not a number" - the one value for which == is never true, not even with itself. See Float64.nan.
const infinity
static infinity: Self = 1.0 / 0.0
Larger than every finite Float32. Float32.negativeInfinity is smaller than every finite one.
const negativeInfinity
static negativeInfinity: Self = -1.0 / 0.0
Smaller than every finite Float32, the one value below every finite one.
fn isInfinite
fn isInfinite(): Bool
Whether the value is Float32.infinity or Float32.negativeInfinity.
fn isFinite
fn isFinite(): Bool
Whether the value is neither nan nor infinite.
fn bits
native fn bits(): UInt32
The IEEE-754 binary32 pattern of the value: the sign in the top bit, then eight bits of exponent and 23 of
mantissa. Nothing is converted, so -0.0, a subnormal and a nan with a payload keep every bit, and
Float32.ofBits gives the same value back: 1.0 is 0x3f800000.
fn ofBits
native static fn ofBits(bits: UInt32): Self
The Float32 whose IEEE-754 binary32 pattern is bits, the inverse of Float32.bits. Every pattern is a
Float32, a signalling nan included, and keeps its bits on the way back.
type Float64
native type Float64 with Signed, Power
A 64-bit floating-point number, and the type of a decimal literal. x ** y is C's pow, so IEEE-754 through and
through - (-8.0) ** (1.0 / 3.0) is nan, and nothing panics; the power by a whole number is Power<Int64> below.
type Decimal
native type Decimal with Signed, Hash
Exact base-10 arithmetic: an unscaled whole number of any size and an Int32 scale, the value being the one divided
by ten to the other (docs/design/DECIMAL.md). 19.90 is 1990 at scale 2, and keeps that scale through +, -
and show.
+, - and * are exact. / answers the exact quotient where it has at most 34 significant digits, and rounds it
to 34 with Rounding.HalfEven where it has more; Decimal.divided is the division that rounds to a scale the
program chooses. % is truncated and takes the sign of the dividend, as on Int64.
Examples
const price: Decimal = 19.99
const quantity: Int = 3
const total = price * Decimal.from(quantity)
print total
print total.rounded(scale: 0, rounding: .HalfUp)
// prints 59.97
// prints 60
Panics
Dividing by zero, with /, % or Decimal.divided, and a scale that leaves Int32: a product whose scales add up
past it, or a quotient whose scale would.
Literals
A number literal that is written where a Decimal is expected is a Decimal of exactly the digits it is written
with, however many, and of the scale it is written with: const price: Decimal = 19.99 is 1999 at scale 2,
1e3 is 1 at scale -3 and 0x10 is 16. Only a scale outside Int32 (1e-3000000000) is an error. A literal
without a Decimal to adapt to is still a Float64 or an Int64.
extend Decimal
extend Decimal
The zero and the one of a Decimal.
const zero
static zero: Self = 0
Zero, the Numeric.zero of an Decimal.
const one
static one: Self = 1
One, the Numeric.one of an Decimal.
type Rounding
type Rounding
How a value is cut where a digit has to go: the mode of Decimal.rounded and Decimal.divided.
case HalfEven
case HalfEven
To the nearest, a tie to the neighbour with an even last digit. The mode of /, banker's rounding.
case HalfUp
case HalfUp
To the nearest, a tie away from zero: 2.5 is 3 and -2.5 is -3. What a person at a till does.
case Down
case Down
Towards zero: the digits are cut off.
case Up
case Up
Away from zero: any dropped non-zero digit raises the magnitude.
case Floor
case Floor
Towards negative infinity.
case Ceiling
case Ceiling
Towards positive infinity.
extend Decimal
extend Decimal
The scale of a Decimal, and rounding to one.
fn rounded
fn rounded(scale: Int32, rounding: Rounding): Self
The value with exactly scale digits after the point. A larger scale than the current one adds zeros and rounds
nothing (2.5 at 3 is 2.500); a smaller one drops digits by rounding; a negative one rounds to tens or
hundreds (1250 at -2 with Rounding.HalfEven is 1200).
fn divided
fn divided(by: Self, scale: Int32, rounding: Rounding): Self
The exact quotient rounded once to scale: 1 / 3 at scale 2 with Rounding.Up is 0.34, where rounding the
34 digits of / again would give 0.33.
Panics
When by is zero, like /.
fn scale
native fn scale(): Int32
How many digits are after the point: 2 for 19.90, 0 for 42, and negative for 1e3.
fn normalized
native fn normalized(): Self
The same value without the trailing zeros of its unscaled number, the scale lowered to match: 19.90 is 19.9,
1200 is 12 at scale -2. Equal values have one normalised form, which is what Hash is computed from.
Panics
When the lowered scale leaves Int32.
fn unscaledText
native fn unscaledText(): String
The unscaled whole number as text, with its sign: 1990 for 19.90, -5 for -0.05.
fn of
static fn of(unscaled: String, scale: Int32): Result<Self, NumberParseError>
The value unscaled / 10^scale, the way back from Decimal.unscaledText and Decimal.scale. unscaled is an
optional sign and decimal digits, nothing else; anything more fails with a NumberParseError.
alias Int
type Int = Int64
The default width for a whole number: Int64.
alias UInt
type UInt = UInt64
The default width for a non-negative whole number: UInt64.
alias Float
type Float = Float64
The default width for a floating-point number: Float64.
extend Int64
extend Int64
The range of an Int64, its zero and one, and reading digits in another base.
const zero
static zero: Self = 0
Zero, the Numeric.zero of an Int64.
const one
static one: Self = 1
One, the Numeric.one of an Int64.
const minimum
static minimum: Self = -9223372036854775807 - 1
The smallest Int64 cannot be written as a positive literal negated (9223372036854775808 alone does not fit
any integer type), so it is spelled the way C spells INT64_MIN: one more than the smallest literal there is.
const maximum
static maximum: Self = 9223372036854775807
The largest Int64.
fn parseDigits
native static fn parseDigits(text: String, radix: Self): Result<Self, NumberParseError>
Digits in another base: Int.parseDigits("ff", radix: 16). No sign, no prefix, _ is allowed between digits.
extend UInt64
extend UInt64
The range of a UInt64, its zero and one, and the two operations that wrap instead of panicking.
const zero
static zero: Self = 0
Zero, the Numeric.zero of a UInt64.
const one
static one: Self = 1
One, the Numeric.one of a UInt64.
const minimum
static minimum: Self = 0
Always 0.
const maximum
static maximum: Self = ~Self.minimum
18446744073709551615: all ones, which is the largest UInt64 there is.
fn addedWrapping
native fn addedWrapping(other: Self): Self
Addition that wraps around instead of panicking. Together with UInt64.multipliedWrapping this is the only
arithmetic in the language that does not panic on overflow, and it exists for one reason: a hash function mixes
bits and needs the wrap. Everywhere else, overflow is a bug and + says so.
An integer literal is read in the type it is expected as, so the offset basis of FNV-1a, which is above the largest
Int64, is written as it is:
const bytes: List<UInt64> = [104, 105]
var hash: UInt64 = 14695981039346656037
for byte in bytes {
hash = (hash ^ byte).multipliedWrapping(1099511628211)
}
print hash
fn multipliedWrapping
native fn multipliedWrapping(other: Self): Self
Multiplication that wraps around instead of panicking. See UInt64.addedWrapping.
extend Float64
extend Float64
The constants and the operations of a Float64 that read as its own, not as a function of a value.
const zero
static zero: Self = 0.0
Zero, the Numeric.zero of an Float64.
const one
static one: Self = 1.0
One, the Numeric.one of an Float64.
const pi
static pi: Self = 3.141592653589793
The ratio of a circle's circumference to its diameter: the Real.pi of a Float64.
const tau
static tau: Self = 6.283185307179586
A whole turn in radians, twice Float64.pi: the Real.tau of a Float64.
const epsilon
static epsilon: Self = 0.0000000000000002220446049250313
The gap between 1.0 and the next Float64, which is two to the power of minus 52: its Real.epsilon.
const e
static e: Self = 2.718281828459045
The base of the natural logarithm.
const nan
static nan: Self = 0.0 / 0.0
"Not a number" - the one value for which == is never true, not even with itself (Float64.isNaN). Named the way
Real.pi is: the compile-time constant evaluator (ir/constant.trb) only allows this one declaration and
Float32.nan to fold to it, because an ordinary expression that produces nan is a mistake and stays an error
(docs/language/modules-and-packages/top-level-code.md, rule 6).
const infinity
static infinity: Self = 1.0 / 0.0
Larger than every finite Float64. Float64.negativeInfinity is smaller than every finite one.
const negativeInfinity
static negativeInfinity: Self = -1.0 / 0.0
Smaller than every finite Float64, the one value below every finite one.
fn squareRoot
native fn squareRoot(): Self
The non-negative square root.
fn floor
native fn floor(): Self
Rounded towards negative infinity.
fn ceiling
native fn ceiling(): Self
Rounded towards positive infinity.
fn round
native fn round(): Self
Rounded to the nearest integer.
fn isNaN
native fn isNaN(): Bool
Whether the value is "not a number" - the one value for which == is never true, not even with itself.
fn isInfinite
fn isInfinite(): Bool
Whether the value is Float64.infinity or Float64.negativeInfinity.
fn isFinite
fn isFinite(): Bool
Whether the value is neither nan nor infinite.
fn bits
native fn bits(): UInt64
The IEEE-754 binary64 pattern of the value: the sign in the top bit, then eleven bits of exponent and 52 of
mantissa. Nothing is converted, so -0.0, a subnormal and a nan with a payload keep every bit, and
Float64.ofBits gives the same value back:
const value = 1.0
const pattern: UInt64 = 0x3ff0000000000000
assert(value.bits() == pattern)
assert(Float64.ofBits(pattern) == value)
fn ofBits
native static fn ofBits(bits: UInt64): Self
The Float64 whose IEEE-754 binary64 pattern is bits, the inverse of Float64.bits. Every pattern is a
Float64, a signalling nan included, and keeps its bits on the way back. A call is never folded into a constant:
const x = Float64.ofBits(...) at the top level is an error, because what it makes may be a nan.
fn isCloseTo
fn isCloseTo(other: Self, tolerance: Self = 0.000001): Bool
Floats are compared with a tolerance: assert(length.isCloseTo(1.0))
The exact comparisons a float has are deliberately different from each other, because IEEE-754 equality is not an equivalence relation and IEEE-754 ordering is not a total order:
- Every operator is IEEE-754:
==,<,<=,>and>=.nan != nan, every comparison with ananon either side isfalse, and0.0 == -0.0. compareis a total order:nanis above everything, and-0.0compares equal to0.0. Sosortedterminates whatever pivot it picks, whatever is in the list.- A float is therefore the one type where an operator and the member behind it disagree, which is why everything
that orders values calls
compareand never writes<=: an IEEE<=would leave ananwhere it started. Float32andFloat64are notHash, so a float is never aMapkey and thenankey does not exist.
extend Float64 with Real
extend Float64 with Real
Float64 is the fast Real: the square root, the rounding and isCloseTo are its own methods already, and the
trigonometry, the exponential and the logarithm are the runtime's thin wrappers over <math.h>.
Pitfalls
- What
sineanswers is what the platform's mathematics library answers, so two machines may differ in the last bit.Fixed(std/linear) is the implementor that does not.
fn sine
native fn sine(): Self
The sine of an angle in radians.
fn cosine
native fn cosine(): Self
The cosine of an angle in radians.
fn tangent
native fn tangent(): Self
The tangent of an angle in radians.
fn arcSine
fn arcSine(): Self
In radians, in [-pi/2, pi/2]; nan answers nan.
Panics
Outside [-1, 1], where no angle has this sine, exactly as Fixed.arcSine of std/linear does: the two
implementors of Real agree about every value both of them hold (docs/design/LINEAR.md, "Numeric policy"). A
ratio that rounding pushed a hair past one is clamped at the call, ratio.clamp(-1.0, 1.0).arcSine(), which is the
total form.
fn arcCosine
fn arcCosine(): Self
In radians, in [0, pi]; nan answers nan.
Panics
Outside [-1, 1], where no angle has this cosine, as Float64.arcSine says.
fn arcTangent
native fn arcTangent(): Self
In radians, in (-pi/2, pi/2).
fn arcTangentDivided
native fn arcTangentDivided(by: Self): Self
The angle of the point (by, self), which is C's atan2(self, by).
fn exponential
native fn exponential(): Self
e raised to this value. An infinity where it does not fit, and never a panic.
fn naturalLogarithm
native fn naturalLogarithm(): Self
The logarithm to the base e: -infinity at zero, nan below it, and never a panic.
fn halved
fn halved(): Self
fn radiansOfDegrees
fn radiansOfDegrees(): Self
fn degreesOfRadians
fn degreesOfRadians(): Self
extend Float64 with Power<Int64>
extend Float64 with Power<Int64>
x ** n for a whole exponent: 2.0 ** 10 and 10.0 ** -3. It is pow with the exponent as a Float64 rather
than repeated squaring, because pow rounds once where squaring rounds at every step, and because squaring towards a
negative power overflows to an infinity before it divides.
Pitfalls
- An exponent beyond
2 ** 53in magnitude has no exactFloat64, and everyFloat64that large is even. The sign an odd exponent gives a negative base is therefore put back by hand; the magnitude of such a power is an infinity, a zero or one anyway.
fn power
fn power(exponent: Int64): Self
extend Int64 with From<Int8>
extend Int64 with From<Int8>
A narrower signed integer always fits: Int.from(byte) for an Int8.
fn from
native static fn from(value: Int8): Self
extend Int64 with From<Int16>
extend Int64 with From<Int16>
A narrower signed integer always fits: Int.from(short) for an Int16.
fn from
native static fn from(value: Int16): Self
extend Int64 with From<Int32>
extend Int64 with From<Int32>
A narrower signed integer always fits: Int.from(word) for an Int32.
fn from
native static fn from(value: Int32): Self
extend Int64 with From<UInt8>
extend Int64 with From<UInt8>
Every unsigned value below the width of an Int64 fits into it: Int.from(byte) for a byte of a String.
fn from
native static fn from(value: UInt8): Self
extend Int64 with From<UInt16>
extend Int64 with From<UInt16>
Every unsigned value below the width of an Int64 fits into it.
fn from
native static fn from(value: UInt16): Self
extend Int64 with From<UInt32>
extend Int64 with From<UInt32>
Every unsigned value below the width of an Int64 fits into it.
fn from
native static fn from(value: UInt32): Self
extend Float64 with From<Int64>
extend Float64 with From<Int64>
Every Int64 is representable as a Float64.
fn from
native static fn from(value: Int64): Self
extend Float64 with From<Float32>
extend Float64 with From<Float32>
Every Float32 widens to Float64 without loss.
fn from
native static fn from(value: Float32): Self
extend Float64 with From<Decimal>
extend Float64 with From<Decimal>
The nearest Float64, a tie to even, as reading the decimal's text would give it. Beyond the range of a Float64 it
is an infinity, and nothing panics.
fn from
native static fn from(value: Decimal): Self
extend Decimal with From<Int64>
extend Decimal with From<Int64>
Every Int64 is a Decimal at scale 0.
fn from
native static fn from(value: Int64): Self
extend Decimal with From<UInt64>
extend Decimal with From<UInt64>
Every UInt64 is a Decimal at scale 0.
fn from
native static fn from(value: UInt64): Self
extend Int8 with TryFrom<String, NumberParseError>
extend Int8 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a whole number, or does not fit an Int8.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Int16 with TryFrom<String, NumberParseError>
extend Int16 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a whole number, or does not fit an Int16.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Int32 with TryFrom<String, NumberParseError>
extend Int32 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a whole number, or does not fit an Int32.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Int64 with TryFrom<String, NumberParseError>
extend Int64 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a whole number, or does not fit an Int64.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend UInt8 with TryFrom<String, NumberParseError>
extend UInt8 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a non-negative whole number, or does not fit a UInt8.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend UInt16 with TryFrom<String, NumberParseError>
extend UInt16 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a non-negative whole number, or does not fit a UInt16.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend UInt32 with TryFrom<String, NumberParseError>
extend UInt32 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a non-negative whole number, or does not fit a UInt32.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend UInt64 with TryFrom<String, NumberParseError>
extend UInt64 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a non-negative whole number, or does not fit a UInt64.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Float32 with TryFrom<String, NumberParseError>
extend Float32 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a decimal number.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Float64 with TryFrom<String, NumberParseError>
extend Float64 with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a decimal number.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Decimal with TryFrom<String, NumberParseError>
extend Decimal with TryFrom<String, NumberParseError>
Fails with a NumberParseError when the text is not a decimal number.
fn tryFrom
native static fn tryFrom(text: String): Result<Self, NumberParseError>
extend Int8 with TryFrom<Int64, NumberRangeError>
extend Int8 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 does not fit an Int8.
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend Int16 with TryFrom<Int64, NumberRangeError>
extend Int16 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 does not fit an Int16.
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend Int32 with TryFrom<Int64, NumberRangeError>
extend Int32 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 does not fit an Int32.
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend UInt8 with TryFrom<Int64, NumberRangeError>
extend UInt8 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 is negative or above 255: the one way from a number to a byte.
Examples
const byte: Result<UInt8, NumberRangeError> = UInt8.tryFrom 200
print byte.isOk()
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend UInt16 with TryFrom<Int64, NumberRangeError>
extend UInt16 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 is negative or does not fit a UInt16.
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend UInt32 with TryFrom<Int64, NumberRangeError>
extend UInt32 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 is negative or does not fit a UInt32.
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend UInt64 with TryFrom<Int64, NumberRangeError>
extend UInt64 with TryFrom<Int64, NumberRangeError>
Fails with a NumberRangeError when the Int64 is negative: every other one fits a UInt64.
fn tryFrom
native static fn tryFrom(value: Int64): Result<Self, NumberRangeError>
extend Int64 with TryFrom<UInt64, NumberRangeError>
extend Int64 with TryFrom<UInt64, NumberRangeError>
Fails with a NumberRangeError when the UInt64 is above the largest Int64.
fn tryFrom
native static fn tryFrom(value: UInt64): Result<Self, NumberRangeError>
extend Int64 with TryFrom<Float64, NumberRangeError>
extend Int64 with TryFrom<Float64, NumberRangeError>
Fails with a NumberRangeError when the Float64 does not fit an Int64, e.g. nan or a value out of range.
fn tryFrom
native static fn tryFrom(value: Float64): Result<Self, NumberRangeError>
extend Float32 with TryFrom<Float64, NumberRangeError>
extend Float32 with TryFrom<Float64, NumberRangeError>
The nearest Float32, ties to even: most Float64 values lose digits on the way. nan and the two infinities pass
through, and a value too small for a Float32 becomes a subnormal or a zero of its sign.
Fails with a NumberRangeError only when a finite Float64 would round to an infinity, from about 3.4e38 on.
Examples
const wide: Float64 = 0.1
const narrowed: Result<Float32, NumberRangeError> = Float32.tryFrom wide
print narrowed.isOk()
fn tryFrom
native static fn tryFrom(value: Float64): Result<Self, NumberRangeError>
extend Int64 with TryFrom<Decimal, NumberRangeError>
extend Int64 with TryFrom<Decimal, NumberRangeError>
Fails with a NumberRangeError unless the Decimal is a whole number that fits an Int64: 19.00 converts and
19.5 does not. Cutting the fraction off is a decision, spelled value.rounded(scale: 0, rounding: .Down) first.
fn tryFrom
native static fn tryFrom(value: Decimal): Result<Self, NumberRangeError>
extend UInt64 with TryFrom<Decimal, NumberRangeError>
extend UInt64 with TryFrom<Decimal, NumberRangeError>
Fails with a NumberRangeError unless the Decimal is a whole number that fits a UInt64.
fn tryFrom
native static fn tryFrom(value: Decimal): Result<Self, NumberRangeError>
extend Int64 with From<Char>
extend Int64 with From<Char>
The code point: Int.from('A') is 65. It is here and not with Char, because an implementation belongs to the
package of the type or to the package of the trait, and Int64 is this package's. The other direction
(Char.tryFrom(65)) is std/text's for the same reason.
fn from
native static fn from(value: Char): Self
type ByteSize
type ByteSize with Show, Compare, Add, Subtract, Multiply<Int64, ByteSize>
A number of bytes: the size of a memory, of a volume, of a limit. It is one Int64, like a Duration, and signed
like one, so the difference of two sizes may be negative.
Int64 makes one in either family of units: 64.megabytes() is 64 000 000 bytes, as a disk is counted, and
16.gibibytes() is 16 times 2 to the power of 30, as a memory is. The members of the same names read it back as a
Float64. Every member is in scope without an import, because this package owns Int64.
Examples
const limit = 64.megabytes()
print limit.bytes()
print 1536.bytes()
print(2.gibibytes() - 512.mebibytes())
// prints 64000000
// prints 1.5 KiB
// prints 1.5 GiB
Pitfalls
megabytesis 10 to the power of 6 andmebibytes2 to the power of 20, as the SI and the IEC names say.showuses the binary units, so64.megabytes()prints61.0 MiB.
Related
Int64.megabytesand the other eight - the short way to write one.
fn bytes
fn bytes(): Int64
As a whole number of bytes, which is exactly what it holds.
fn fraction
fn fraction(of: ByteSize): Float64
As a fraction of whole: memory.used().fraction(of: memory.total) is between 0 and 1. A whole of zero bytes
answers what Float64 division by zero answers.
fn kilobytes
fn kilobytes(): Float64
In kilobytes of 1000 bytes, as a disk is counted.
fn megabytes
fn megabytes(): Float64
In megabytes of 1000 kilobytes.
fn gigabytes
fn gigabytes(): Float64
In gigabytes of 1000 megabytes.
fn terabytes
fn terabytes(): Float64
In terabytes of 1000 gigabytes.
fn kibibytes
fn kibibytes(): Float64
In kibibytes of 1024 bytes, as a memory is counted.
fn mebibytes
fn mebibytes(): Float64
In mebibytes of 1024 kibibytes.
fn gibibytes
fn gibibytes(): Float64
In gibibytes of 1024 mebibytes.
fn tebibytes
fn tebibytes(): Float64
In tebibytes of 1024 gibibytes.
fn compare
fn compare(other: Self): Ordering
Which of the two sizes is the smaller one.
fn add
fn add(other: Self): Self
The two sizes together. Panics where the sum does not fit, as every Int64 addition does.
fn subtract
fn subtract(other: Self): Self
How much larger this size is than other: negative where it is smaller.
fn multiply
fn multiply(other: Int64): Self
The size other times over: 4.kibibytes() * 3. Panics where the product does not fit.
fn show
fn show(): String
The largest binary unit with at least one of it, to one decimal: 512 B, 1.5 KiB, 15.9 GiB. Below 1024 bytes
it is the whole number of bytes, and a negative size keeps its sign: -2.0 KiB.
extend Int64
extend Int64
A ByteSize of this many bytes, in either family of units. The Int64 multiplication under each panics where the
bytes do not fit, which is above 8 exbibytes.
fn bytes
fn bytes(): ByteSize
A ByteSize of exactly this many bytes: 512.bytes().
fn kilobytes
fn kilobytes(): ByteSize
A ByteSize of this many kilobytes of 1000 bytes: 4.kilobytes().
fn megabytes
fn megabytes(): ByteSize
A ByteSize of this many megabytes of 1000 kilobytes: 64.megabytes(), the sandbox's default limit.
fn gigabytes
fn gigabytes(): ByteSize
A ByteSize of this many gigabytes of 1000 megabytes.
fn terabytes
fn terabytes(): ByteSize
A ByteSize of this many terabytes of 1000 gigabytes.
fn kibibytes
fn kibibytes(): ByteSize
A ByteSize of this many kibibytes of 1024 bytes: 4.kibibytes(), a page of most systems.
fn mebibytes
fn mebibytes(): ByteSize
A ByteSize of this many mebibytes of 1024 kibibytes.
fn gibibytes
fn gibibytes(): ByteSize
A ByteSize of this many gibibytes of 1024 mebibytes.
fn tebibytes
fn tebibytes(): ByteSize
A ByteSize of this many tebibytes of 1024 gibibytes.