essenceDocumentation
essenceDocs
on this pageAt a glance
Coming from JavaScript?

Algebraic

type

Exact irrational numbers such as square roots: arithmetic, comparison, rounding and printing.

Taught on: Numbers.

At a glance

Declared
namespace Algebraic for Algebraic

Equality, ordering and printing

is

on Algebraic

is(_ other: Algebraic) -> Boolean

Answers whether both Algebraics are the same number.

Normal forms decide the answer exactly. No approximation is consulted.

NameTypeDescription
_Algebraicthe Algebraic to compare with

true when the numbers are equal.

Example
constant golden = Number.GoldenRatio
constant rootFive = golden::multiply(with 2)::subtract(1)

expect rootFive::is(golden::subtract(1/2)::multiply(with 2))
expect rootFive::is(golden)::negate()

compare

on Algebraic

compare(to other: Algebraic) -> Ordering

Orders the Algebraic against another Algebraic.

The comparison is symbolic, so it is exact.

NameTypeDescription
toAlgebraicthe Algebraic to order against

Ordering#Less, Ordering#Equal or Ordering#Greater.

Example
constant golden = Number.GoldenRatio
constant rootFive = golden::multiply(with 2)::subtract(1)

expect golden::compare(to rootFive)::is(#Less)
expect rootFive::compare(to golden::add(1/2))::is(#Greater)

toString

on Algebraic

Answers the Algebraic as a String, in the exact symbolic form or in the named format.

The form is √2, 3·√2 or 1 + √2 when no format is named, and #Fraction names that same form. The #Decimal format writes the expansion, to at most 80 digits, which is the cap a Rational writes a non-terminating expansion at. A count of places writes exactly that many digits after the point.

toString() -> String

Answers the Algebraic as a String, in the exact symbolic form: √2, 3·√2 or 1 + √2.

One radical has one printed form, with one exception. Normalisation divides out square factors up to 65536, so a radicand p²·q with both primes above that is printed as written. The equal p·√q prints in the normalised form.

Example
expect 2::squareRoot()::toString()::is("√2")
expect 18::squareRoot()::toString()::is("3·√2")
expect Number.GoldenRatio::toString()::is("1/2 + 1/2·√5")
toString(as format: NumberFormat) -> String

Answers the Algebraic as a decimal, or in the exact symbolic form, in the named format.

The #Decimal format rounds the expansion at the eightieth digit and writes it. An irrational expansion never ends, so the cap is always reached. Trailing zeros the rounding leaves are dropped, as they are for any Rational. The #Percent format writes one hundred times that same reading, taken two digits deeper so that eighty still stand after the point. The #Scientific format writes eighty digits after the point of the mantissa, and the power of ten after an e. The reading is taken at the eightieth digit of the mantissa, wherever the value falls. A value below one is read deeper than eighty places. The #Fraction format writes the symbolic form, since no ratio of two Integers is this number.

NameTypeDescription
asNumberFormatthe form to represent the Algebraic in

the String representation of the Algebraic.

Example
constant root = 2::squareRoot()

expect root::toString(as #Decimal)::starts(with "1.41421356237")
expect root::toString(as #Decimal)::length()::is(82)
expect root::toString(as #Fraction)::is("√2")
toString(
	as format: NumberFormat,
	toPlaces count: Integer,
	toward direction: Rounding = #Nearest,
) -> String

Answers the Algebraic as a decimal with exactly that many places.

The digits are padded with zeroes where the rounded value is shorter. The last digit kept is rounded in the named direction, and #Nearest is what a call that names none is given. A count below one rounds to a whole number, and no point is written. The #Percent format takes the count the same way, on one hundred times the value. The #Scientific format counts the digits of the mantissa after the point, at every magnitude. The value is read as many digits past the count as its own power of ten falls below zero. The #Fraction format ignores both the count and the direction, and writes the symbolic form.

NameTypeDescription
asNumberFormatthe form to represent the Algebraic in
toPlacesIntegerhow many digits to write after the point
towardRounding = #Nearestthe direction to round the last digit in, #Nearest when it is left out

the String representation of the Algebraic.

Example
constant root = 2::squareRoot()

expect root::toString(as #Decimal, toPlaces 3)::is("1.414")
expect root::toString(as #Decimal, toPlaces 3, toward #Up)::is("1.415")
expect root::toString(as #Percent, toPlaces 1)::is("141.4%")

isNot

on Algebraic · provided by Equatable

isNot(_ other: Algebraic) -> Boolean

Answers whether the values differ.

NameTypeDescription
_Algebraicthe value to compare with

true when the values differ.

Example
expect "Ada"::isNot("Grace")
expect 3::isNot(3)::negate()

Arithmetic

add

on Algebraic

Answers the exact sum of the Algebraic and a number.

Two Algebraics over the same radical stay in the slice. Their radical parts can also cancel, which leaves a Rational. Two roots of different numbers have no sum in this slice, and the answer is empty. The defaultingTo: entry answers the given value in place of empty.

add(_ other: Integer) -> Algebraic

Answers the exact sum of the Algebraic and an Integer.

An Integer shifts the rational part and leaves the radical in place, so the sum is again an Algebraic.

NameTypeDescription
_Integerthe Integer to add

the exact sum.

Example
expect 2::squareRoot()::add(1)::toString()::is("1 + √2")
expect 2::squareRoot()::add(-1)::toString()::is("-1 + √2")
add(_ other: Rational) -> Algebraic

Answers the exact sum of the Algebraic and a Rational.

A Rational shifts the rational part and leaves the radical in place, so the sum is again an Algebraic.

NameTypeDescription
_Rationalthe Rational to add

the exact sum.

Example
expect 2::squareRoot()::add(1/2)::toString()::is("1/2 + √2")
add(_ other: Algebraic) -> Optional<Rational | Algebraic>

Answers the exact sum of the two Algebraics.

Over the same radical the sum stays in the slice, and can collapse to a Rational. Over different radicals the sum falls outside what an Algebraic holds, and the answer is empty.

NameTypeDescription
_Algebraicthe Algebraic to add

the sum, or nothing when the radicals differ.

Example
constant golden = Number.GoldenRatio
constant conjugate = golden::negate()::add(1)

expect golden::add(golden)::is(golden::multiply(with 2))
expect golden::add(conjugate)::is(1/1)
add(
	_ other: Algebraic,
	defaultingTo fallback: Rational | Algebraic,
) -> Rational | Algebraic

Answers the exact sum of the two Algebraics.

Over different radicals there is no sum, and the answer is the given value.

NameTypeDescription
_Algebraicthe Algebraic to add
defaultingToRational | Algebraicthe value to answer with when there is no sum

the sum, or the given value in its place.

Example
constant golden = Number.GoldenRatio

expect golden::add(golden, defaultingTo 0/1)::toString()::is("1 + √5")

subtract

on Algebraic

Answers the exact difference of the Algebraic and a number.

Subtracting an equal radical part leaves a Rational. Two roots of different numbers have no difference in this slice, and the answer is empty. The defaultingTo: entry answers the given value in place of empty.

subtract(_ other: Integer) -> Algebraic

Answers the exact difference of the Algebraic and an Integer.

An Integer shifts the rational part and leaves the radical in place, so the difference is again an Algebraic.

NameTypeDescription
_Integerthe Integer to subtract

the exact difference.

Example
expect 2::squareRoot()::subtract(1)::toString()::is("-1 + √2")
subtract(_ other: Rational) -> Algebraic

Answers the exact difference of the Algebraic and a Rational.

A Rational shifts the rational part and leaves the radical in place, so the difference is again an Algebraic.

NameTypeDescription
_Rationalthe Rational to subtract

the exact difference.

Example
expect 2::squareRoot()::subtract(1/2)::toString()::is("-1/2 + √2")
subtract(_ other: Algebraic) -> Optional<Rational | Algebraic>

Answers the exact difference of the two Algebraics.

Over the same radical the difference stays in the slice, and can collapse to a Rational. Over different radicals there is no difference, and the answer is empty.

NameTypeDescription
_Algebraicthe Algebraic to subtract

the difference, or nothing when the radicals differ.

Example
constant golden = Number.GoldenRatio

expect golden::subtract(golden::multiply(with 2))::is(golden::negate())
expect golden::subtract(golden::subtract(1))::is(1/1)
subtract(
	_ other: Algebraic,
	defaultingTo fallback: Rational | Algebraic,
) -> Rational | Algebraic

Answers the exact difference of the two Algebraics.

Over different radicals there is no difference, and the answer is the given value.

NameTypeDescription
_Algebraicthe Algebraic to subtract
defaultingToRational | Algebraicthe value to answer with when there is no difference

the difference, or the given value in its place.

Example
constant golden = Number.GoldenRatio
constant smaller = golden::subtract(1)

expect golden::subtract(smaller, defaultingTo 0/1)::is(1)

multiply

on Algebraic

Answers the exact product of the Algebraic and a number.

A radical times itself turns rational: √2 · √2 is 2. Multiplying by zero answers zero. Multiplying by a NonZeroInteger or a NonZeroRational keeps the radical, so those entries answer an Algebraic. The defaultingTo: entry answers the given value in place of empty.

multiply(with other: Integer) -> Algebraic | Rational

Answers the exact product of the Algebraic and an Integer.

An Integer scales both parts and leaves the radical in place. A zero factor collapses the product to the Rational zero.

NameTypeDescription
withIntegerthe Integer to multiply with

the exact product, an Algebraic or a Rational.

Example
constant root = 2::squareRoot()
constant copies = 3

expect root::multiply(with copies)::toString()::is("3·√2")
expect root::multiply(with 0)::is(0)
multiply(with other: Rational) -> Algebraic | Rational

Answers the exact product of the Algebraic and a Rational.

A Rational scales both parts and leaves the radical in place. A zero factor collapses the product to the Rational zero.

NameTypeDescription
withRationalthe Rational to multiply with

the exact product, an Algebraic or a Rational.

Example
constant root = 2::squareRoot()
constant half = 1/2

expect root::multiply(with half)::toString()::is("1/2·√2")
expect root::multiply(with 0/1)::is(0)
multiply(with other: Algebraic) -> Optional<Rational | Algebraic>

Answers the exact product of the two Algebraics.

Over the same radical the product stays exact: √2 · √2 is 2. Two pure radicals combine across radicals: √2 · √3 is √6. Anything else is empty.

NameTypeDescription
withAlgebraicthe Algebraic to multiply with

the product, or nothing when there is none.

Example
constant golden = Number.GoldenRatio

expect golden::multiply(with golden)::is(golden::add(1))
expect golden::multiply(with golden::subtract(1))::is(1/1)
multiply(
	with other: Algebraic,
	defaultingTo fallback: Rational | Algebraic,
) -> Rational | Algebraic

Answers the exact product of the two Algebraics.

Where there is no product, the answer is the given value.

NameTypeDescription
withAlgebraicthe Algebraic to multiply with
defaultingToRational | Algebraicthe value to answer with when there is no product

the product, or the given value in its place.

Example
constant golden = Number.GoldenRatio
constant squared = golden::multiply(with golden, defaultingTo 0/1)

expect squared::is(golden::add(1))
multiply(with other: NonZeroInteger) -> Algebraic

Answers the exact product of the Algebraic and a factor proven not to be zero.

A non-zero Integer scales both parts and leaves the radical in place. The answer is again an Algebraic rather than a Union.

NameTypeDescription
withNonZeroIntegerthe factor, proven not to be zero

the exact product.

Example
expect 2::squareRoot()::multiply(with 3)::toString()::is("3·√2")
expect Number.GoldenRatio::multiply(with 2)::toString()::is("1 + √5")
multiply(with other: NonZeroRational) -> Algebraic

Answers the exact product of the Algebraic and a Rational factor proven not to be zero.

A Rational that is not zero scales both parts and leaves the radical in place. The answer is again an Algebraic rather than a Union.

NameTypeDescription
withNonZeroRationalthe factor, proven not to be zero

the exact product.

Example
expect 2::squareRoot()::multiply(with 1/2)::toString()::is("1/2·√2")

divide

on Algebraic

Answers the exact quotient of the Algebraic and a number.

Dividing by an Integer or a Rational is empty only for zero. Dividing by a NonZeroInteger or a NonZeroRational can not fail, because those divisors are proven. Dividing by an Algebraic multiplies by its reciprocal, which the conjugate always gives. That quotient is empty wherever the matching product is empty. The defaultingTo: entries answer the given value in place of empty.

divide(by other: Integer) -> Optional<Algebraic>

Answers the exact quotient of the Algebraic and an Integer.

A divisor that is not zero scales both parts and leaves the radical in place. A zero divisor answers empty.

NameTypeDescription
byIntegerthe divisor

the exact quotient, or nothing when the divisor is zero.

Example
constant golden = Number.GoldenRatio
constant divisor = 2

expect golden::divide(by divisor)::is(golden::multiply(with 1/2))
expect golden::divide(by 0)::isEmpty()
divide(by other: Rational) -> Optional<Algebraic>

Answers the exact quotient of the Algebraic and a Rational.

A divisor that is not zero scales both parts and leaves the radical in place. A zero divisor answers empty.

NameTypeDescription
byRationalthe divisor

the exact quotient, or nothing when the divisor is zero.

Example
constant golden = Number.GoldenRatio
constant half = 1/2

expect golden::divide(by half)::is(golden::multiply(with 2))
expect golden::divide(by 0/1)::isEmpty()
divide(by other: Algebraic) -> Optional<Rational | Algebraic>

Answers the exact quotient of the two Algebraics.

The divisor's conjugate gives its reciprocal, and the quotient is that product. It is empty wherever the matching product is empty.

NameTypeDescription
byAlgebraicthe divisor

the quotient, or nothing when there is none.

Example
constant golden = Number.GoldenRatio

expect golden::divide(by golden)::is(1/1)
expect golden::divide(by golden::subtract(1))::is(golden::add(1))
divide(by other: Integer, defaultingTo fallback: Algebraic) -> Algebraic

Answers the exact quotient of the Algebraic and an Integer.

A zero divisor answers the given value.

NameTypeDescription
byIntegerthe divisor
defaultingToAlgebraicthe value to answer with when there is no quotient

the quotient, or the given value in its place.

Example
constant golden = Number.GoldenRatio
constant halved = golden::multiply(with 1/2)
constant divisor = 2

expect golden::divide(by divisor, defaultingTo golden)::is(halved)
expect golden::divide(by 0, defaultingTo golden)::is(golden)
divide(
	by other: Rational,
	defaultingTo fallback: Algebraic,
) -> Algebraic

Answers the exact quotient of the Algebraic and a Rational.

A zero divisor answers the given value.

NameTypeDescription
byRationalthe divisor
defaultingToAlgebraicthe value to answer with when there is no quotient

the quotient, or the given value in its place.

Example
constant golden = Number.GoldenRatio
constant doubled = golden::multiply(with 2)
constant half = 1/2

expect golden::divide(by half, defaultingTo golden)::is(doubled)
expect golden::divide(by 0/1, defaultingTo golden)::is(golden)
divide(
	by other: Algebraic,
	defaultingTo fallback: Rational | Algebraic,
) -> Rational | Algebraic

Answers the exact quotient of the two Algebraics.

Where there is no quotient, the answer is the given value.

NameTypeDescription
byAlgebraicthe divisor
defaultingToRational | Algebraicthe value to answer with when there is no quotient

the quotient, or the given value in its place.

Example
constant golden = Number.GoldenRatio

expect golden::divide(by golden, defaultingTo 0/1)::is(1)
divide(by other: NonZeroInteger) -> Algebraic

Answers the exact quotient of the Algebraic and a divisor proven not to be zero.

The division can not fail, so the answer is the quotient itself rather than an Optional.

NameTypeDescription
byNonZeroIntegerthe divisor, proven not to be zero

the exact quotient.

Example
expect 2::squareRoot()::divide(by 2)::toString()::is("1/2·√2")
divide(by other: NonZeroRational) -> Algebraic

Answers the exact quotient of the Algebraic and a Rational divisor proven not to be zero.

The division can not fail, so the answer is the quotient itself rather than an Optional.

NameTypeDescription
byNonZeroRationalthe divisor, proven not to be zero

the exact quotient.

Example
expect 2::squareRoot()::divide(by 1/2)::toString()::is("2·√2")

raise

on Algebraic

raise(to exponent: Integer) -> Rational | Algebraic

Answers the Algebraic raised to the given power, exactly.

The slice is closed under Integer powers, so every power is exact. A power can cancel the radical, so 2::squareRoot() squared is the Rational 2. A negative exponent answers the power of the reciprocal, which always exists, since an Algebraic is never zero. A zero exponent answers 1.

NameTypeDescription
toIntegerthe exponent

the exact power, an Algebraic or a Rational.

Example
constant root = 2::squareRoot()

expect root::raise(to 2)::is(2)
expect root::raise(to 3)::toString()::is("2·√2")
expect root::raise(to -2)::is(1/2)

Comparing

isLessThan

on Algebraic · provided by Comparable

isLessThan(_ other: Algebraic) -> Boolean

Answers whether the value is strictly below another.

NameTypeDescription
_Algebraicthe value to compare with

true when the value is below the given one.

Example
expect 3::isLessThan(5)
expect 5::isLessThan(5)::negate()

isLessThanOrEqualTo

on Algebraic · provided by Comparable

isLessThanOrEqualTo(_ other: Algebraic) -> Boolean

Answers whether the value is below another, or equal to it.

NameTypeDescription
_Algebraicthe value to compare with

true when the value is below the given one or equal to it.

Example
expect 3::isLessThanOrEqualTo(5)
expect 5::isLessThanOrEqualTo(5)

isGreaterThan

on Algebraic · provided by Comparable

isGreaterThan(_ other: Algebraic) -> Boolean

Answers whether the value is strictly above another.

NameTypeDescription
_Algebraicthe value to compare with

true when the value is above the given one.

Example
expect "pear"::isGreaterThan("apple")
expect "pear"::isGreaterThan("pear")::negate()

isGreaterThanOrEqualTo

on Algebraic · provided by Comparable

isGreaterThanOrEqualTo(_ other: Algebraic) -> Boolean

Answers whether the value is above another, or equal to it.

NameTypeDescription
_Algebraicthe value to compare with

true when the value is above the given one or equal to it.

Example
expect 5::isGreaterThanOrEqualTo(3)
expect 5::isGreaterThanOrEqualTo(5)

isBetween

on Algebraic · provided by Orderable

isBetween(_ lower: Algebraic, and upper: Algebraic) -> Boolean

Answers whether the value lies between the two given ones, both included.

The two bounds name the same range in either order: 7::isBetween(10, and 1) is true, and 15::isBetween(10, and 1) is false.

NameTypeDescription
_Algebraicone bound of the range, included
andAlgebraicthe other bound of the range, included

true when the value is within the bounds.

Example
expect 7::isBetween(1, and 10)
expect 7::isBetween(10, and 1)
expect 15::isBetween(10, and 1)::negate()

clamp

on Algebraic · provided by Orderable

clamp(between lowest: Algebraic, and highest: Algebraic) -> Algebraic

Answers the value, pulled into the given bounds.

The answer is the lower bound when the value is below it. It is the upper bound when the value is above it, and the value itself otherwise. The two bounds name the same range in either order: 7::clamp(between 10, and 1) is 7, and 15::clamp(between 10, and 1) is 10.

NameTypeDescription
betweenAlgebraicone bound of the range
andAlgebraicthe other bound of the range

the clamped value.

Example
expect 7::clamp(between 1, and 10)::is(7)
expect 15::clamp(between 1, and 10)::is(10)
expect -4::clamp(between 10, and 1)::is(1)

Testing

isPositive

on Algebraic

isPositive() -> Boolean

Answers whether the Algebraic is above zero.

The sign of a + b·√d is exactly decidable. No approximation is consulted.

Example
constant root = 2::squareRoot()

expect root::subtract(1.4142)::isPositive()
expect root::subtract(1.4143)::isPositive()::negate()

isNegative

on Algebraic

isNegative() -> Boolean

Answers whether the Algebraic is below zero.

The sign of a + b·√d is exactly decidable. No approximation is consulted.

Example
constant root = 2::squareRoot()

expect root::subtract(1.4143)::isNegative()
expect root::isNegative()::negate()

isZero

on Algebraic

isZero() -> Boolean

Answers whether the Algebraic is exactly zero.

An Algebraic carries a radical with a coefficient that is not zero, so the answer is always false.

Example
expect 2::squareRoot()::isZero()::negate()

isWholeNumber

on Algebraic

isWholeNumber() -> Boolean

Answers whether the Algebraic is a whole number.

An Algebraic is irrational, so it is never whole and the answer is always false.

Example
expect 2::squareRoot()::isWholeNumber()::negate()

Sign and rounding

absolute

on Algebraic

absolute() -> Algebraic

Answers the Algebraic without its sign, which is its distance from zero.

The sign of a + b·√d is exactly decidable. No approximation is consulted.

Example
constant root = 2::squareRoot()

expect root::negate()::absolute()::is(root)
expect root::subtract(2)::absolute()::is(root::negate()::add(2))

negate

on Algebraic

negate() -> Algebraic

Answers the Algebraic with its sign flipped.

Negating an irrational leaves it irrational, so the answer is again an Algebraic.

Example
constant root = 2::squareRoot()

expect root::negate()::toString()::is("-√2")
expect root::negate()::negate()::is(root)

approximate

on Algebraic

approximate(
	toPlaces places: NonNegativeInteger,
	toward direction: Rounding = #Nearest,
) -> Rational

Answers the Algebraic as a Rational on a decimal grid of the given width.

Five places answer the value rounded to hundred-thousandths, so 2::squareRoot() over five places answers 141421/100000. This Method is where a Program asks for digits in place of the exact value. The answer is exact all the same: it is the step of that grid the value rounds to. A width of no places answers a whole number, as a Rational.

NameTypeDescription
toPlacesNonNegativeIntegerhow many decimal places the grid keeps
towardRounding = #Nearestthe direction to round in, #Nearest when it is left out

the value on the grid the width names.

Example
constant root = 2::squareRoot()

expect root::approximate(toPlaces 5)::is(1.41421)
expect root::approximate(toPlaces 2, toward #Up)::is(1.42)
expect root::approximate(toPlaces 0)::is(1/1)

round

on Algebraic

Answers the Algebraic rounded in the named direction.

The direction is #Nearest when a call names none. An irrational is never exactly halfway between two steps, so #Nearest and #NearestEven answer alike here. The other directions answer the floor for #Down, the ceiling for #Up, and the step towards zero for #TowardZero. Naming a count of places rounds to a decimal grid of that width instead, and answers a Rational.

round(toward direction: Rounding = #Nearest) -> Integer

Answers the Algebraic as an Integer, rounded in the named direction.

NameTypeDescription
towardRounding = #Nearestthe direction to round in, #Nearest when it is left out

the rounded Integer.

Example
constant root = 2::squareRoot()

expect root::round()::is(1)
expect root::round(toward #Up)::is(2)
round(
	toPlaces places: Integer,
	toward direction: Rounding = #Nearest,
) -> Rational

Answers the Algebraic rounded to a decimal grid of the given width.

Two places round to hundredths. The answer is what approximate(toPlaces:toward:) answers, and a count below one rounds to a whole number. The entry stands here so that a Number receiver reaches round at every width, whichever kind it holds.

NameTypeDescription
toPlacesIntegerhow many decimal places to keep
towardRounding = #Nearestthe direction to round in, #Nearest when it is left out

the rounded Rational.

Example
constant root = 2::squareRoot()

expect root::round(toPlaces 2)::is(1.41)
expect root::round(toPlaces 2, toward #Up)::is(1.42)
expect root::round(toPlaces 0)::is(1/1)

decimalExponent

on Algebraic

decimalExponent() -> Integer

Answers the power of ten at or below the Algebraic's distance from zero.

This is the exponent the #Scientific format writes after the e. A value between one and ten answers zero, and a value between a tenth and one answers minus one. The enclosure widens until it falls inside one such power of ten. That always happens: an Algebraic is irrational, so it is never a power of ten itself.

the exponent of the power of ten the value falls on.

Example
constant golden = Number.GoldenRatio

expect golden::decimalExponent()::is(0)
expect golden::subtract(1)::decimalExponent()::is(-1)
expect golden::multiply(with 10)::decimalExponent()::is(1)
esc