Skip to content

JavaScript library for surreal numbers (Conway normal form), ordinal numbers and transfinite sequences

Notifications You must be signed in to change notification settings

Ming-Tang/Conway

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

conway

Library for representing surreal numbers in Conway normal form.

Also includes functionalities for dealing with ordinal numbers and transfinite sequences.

Summary

Types

Surreal number: Conway

Represents a surreal number that can be expressed in terms of a finite expression in Conway normal form.

Internally the sum is represented as an array of [exponent, coefficient] pairs sorted by the exponent descending with zero coefficients discarded.

The exponent is either a real number (if possible) or a Conway (if it must be represented as an expression).

The real coefficients can be number or bigint.

The upper limit of this representation is epsilon_0 (e0 = w^e0) and the lower limit is its negation.

The upper limit of the birthday is the ordinal $\epsilon_0$.

Ordinal number: Ord

The Conway class is re-used for representing ordinal numbers in Cantor normal form.

The isOrdinal property determines if a particular value is an ordinal number, and there are ordinal arithmetic operations as well.

Type-safe tracking of isOrdinal

The first type parameter of Conway keeps track of a value is definitely an ordinal number of not. Conway<true> indicates the values of the type are definitely ordinal numbers, while Conway or Conway<boolean> does not care if the values are ordinal numbers or not.

The type alias Ord is defined to be Conway, while Ord0 = Real | Ord. Most functions that reference to ordinal numbers use these type aliases.

Some functions overload based on the isOrdinal property of the arguments to determine if the return type is ordinal or not.

These functions are: mono, mono1, ensure, add, mult

// positive bigints are inferred to be Ord0
mult(one, mono1(4n)) // mult(Ord0, Ord0): Ord0
add(one, 3n) // add(Ord0, Ord0): Ord0

Transfinite sequence: Seq

A transfinite sequence is a sequence indexed by an ordinal number. The index cannot be unwrapped in Seq-related APIs.

The length property determines the order type of the sequence.

interface Seq<T> {
    length: Ord;
    index(index: Ord): T;
}

Constant sequences: isConstant

If all elements of a Seq<T> equals to the first element, the implementations of Seq<T> can set the field isConstant = true. Some sequence functions will take isConstant into account simplified the sequences generated.

If the Seq<T> has length zero or one, isConstant should be true.

Examples of transfinite sequences

import { ... } from "conway/seq";

// order type w, [1, 2, 3, 1, 2, 3, 1, 2, 3, ...]
cycleArray([1, 2, 3]);

// order type w + 2, [ 2, 3, 4, 2, 3, 4, ... | 0, 1 ]
const c2 = concat(cycleArray([2, 3, 4]), fromArray([0, 1]));
c2.index(unit.add(1)); // c2[w + 1] = 1

// Natural numbers reordered with odd numbers before even numbers
// order type w.2, [ 0, 2, 4, 6, ... | 1, 3, 5, 7, ... ]
concat(mapNatural((i) => i * 2), mapNatural((i) => i * 2 + 1));

API Design

Real numbers

Real numbers (type alias Real) are represented as JavaScript number or bigint.

Unwrapped vs. wrapped

Many surreal and ordinal operations take either a real number or a Conway as an input or output, allowing the caller to avoid wrapping finite values using fromReal or ensure and the function can return an unwrapped real number if possible.

The type alias Conway0 and Ord0 correspond to either a value in either wrapped or unwrapped form.

The exponents in the array of tuple representations of Conway/Cantor normal forms area always unwrapped reals if possible.

The maybeDowngrade function takes a Conway and returns an unwrapped Real if possible, otherwise the argument itself is returned.

type Conway = ...;
type Conway0 = Conway | Real;

type Ord = ...;
type Ord0 = Ord | Real;

Module export

import { ... } from "conway/op";

// sub(a: Conway0, b: Conway0): Conway0
mult(sub(num1, num2))

sub(3, 2) // => 1 : Real

Class method

When a module containing the operation is imported, it can be used as a class method of Conway as well.

The class methods can take unwrapped values as arguments, but they will never return unwrapped values.

// num1, num2 : Conway
// num.sub : (b: Conway0): Conway
num1.sub(num2)

fromReal(3).sub(1) // => fromReal(2) : Conway
fromReal(3).sub(fromReal(1)) // => fromReal(2) : Conway

Creation

import { ... } from "conway/op"

zero // 0
one // 1
unit // w (omega)
real(r) // real number value
mono(coeff, exponent) // w^exponent . coeff
mono1(exponent) // w^exponent
new Conway([[p1, c1], [p2, c2], [p3, c3]]); // from a list of [power, coeff] tuples

zero, one and unit are typed as Ord and this can cause type errors for an mutable variable intended not to be ordinals. In that case, specify the type for the variable explicitly.

let sum: Conway = zero;
for (...) {
    const d: Conway = ...;
    sum = add(sum, d);
}

Operations

Creation

Applies to both surreal numbers and ordinal numbers.

Operation Code Description
$0$ zero Zero
$1$ one One
$\omega$ unit Omega
$\sum_i \omega^{p_i} c_i$ create([[p0, c0], ...]) or new Conway(...) Construct from Conway/Cantor normal form given an array or Iterable of [power, coefficient] tuples.
$\omega^p$ mono1(p) Monomial (given coefficient of 1 and power p)
$\omega^p c$ mono(c, p) Monomial (given coefficient c and power p)
N/A ensure(r) Given a real number, convert it to Conway, otherwise return the value itself.
N/A fromReal(r) Given a real number, construct a Conway representing it.

Comparison

Let a, b be ordinal numbers or surreal numbers.

Operation Code Description
$a = b$ eq(a, b) Equals
$a \ne b$ ne(a, b) Not equals
$a &gt; b$ gt(a, b) Greater than
$a \ge b$ ge(a, b) Greater than or equals
$a &lt; b$ lt(a, b) Less than
$a \le b$ le(a, b) Less than or equals
N/A compare(a, b) Array#sort comparator

Conway/Cantor normal form

Let a be a surreal number or ordinal number.

Code Description
Conway The type for Conway/Cantor normal forms.
a.length Number of terms
a.getByIndex(i) Get the [power, coefficient] tuple by index i
a.has(p) Has non-zero term for power p?
a.get(p) Get coefficient (or zero) for power p
[...a], a[Symbol.iterator] Iterate the [power, coefficient] tuples in descending order bypower
+a, a[Symbol.toPrimitive]("number") Convert the value to a number. If the value is infinite +Infinity or -Infinity is returned
a.toString() Return a readable representation for the term
a.toJson() Return a JSON structure for the term

Surreal number operations

Let a, b be surreal numbers.

Operation Code Description
$a + b$ add(a, b) Addition
$a - b$ sub(a, b) Subtraction
$a \times b$ mult(a, b) Multiplication
$a / b$ divRem(a, b) Surreal long division (returns quotient, remainder tuple)
$a / b$ divRemIters(a, b, n) Repeat surreal long division by n times and returns (quotient, remainder)
$-a$ neg(a) Negation
$a ^ b$ pow(a, b) Exponentiation
$\exp(a)$ exp(a) Exponential
$\log(a)$ log(a, n) Logarithm (to the first n terms if infinite sum is needed)

Surreal number properties

Let a = inf + r + low be a surreal number that can be decomposed into a sum of

  • purely infinite value inf $\ \in \mathbb{J}$
  • real value r $\ \in \mathbb{R}$
  • and purely infinitesimal value low $\ \in \mathbf{No}^\prec$
Operation Code Description
$b(a)$ birthday(a) Birthday of a surreal number (returns an ordinal number)
inf a.infinitePart Purely infinite part, or zero
r a.realPart Real part, or zero
low a.infinitesimalPart Purely infinitesimal part, or zero
N/A a.realValue If a is purely real (inf = low = 0), its real part. Otherwise, null
$a &gt; 0$ isPositive(a) Is a positive?
$a &lt; 0$ isNegative(a) Is a negative?
$a = 0$ isZero(a) a equals zero?
$a = 1$ isOne(a) a equals one?
$a = \omega$ isUnit(a) a equals omega?
$a &gt; \mathbb{R}$ isAboveReals(a) Is a infinite (or inf is positive)?
$a &lt; -\mathbb{R}$ isBelowNegativeReals(a) Is -a infinite (or inf is negative)?
$a \in \text{Ord}$ isOrdinal(a) a represents an ordinal number?

Ordinal number operations

Let a, b be ordinal numbers.

Operation Code Description
$a + b$ ordinalAdd(a, b) Ordinal addition
$a - b$ ordinalRightSub(b, a) Ordinal right subtraction (solution to $a + ? = b$)
$a \times b$ ordinalMult(a, b) Ordinal multiplication
$a / b$ ordinalDivRem(b, a) Ordinal division and remainder (returns [q, r] where $a = b q + r$ and $q$ is maximized)
$a^b$ ordinalPow(a, b) Ordinal exponentiation
$a\oplus b$ add(a, b) Natural sum (implemented as surreal sum)
$a \otimes b$ mult(a, b) Natural product (implemented as surreal product)

Install

To install dependencies:

bun install

To run:

bun run index.ts

About

JavaScript library for surreal numbers (Conway normal form), ordinal numbers and transfinite sequences

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published