Browse the documentation

AEL 1.0.0

Numbers

AEL, the Agent Engineering Language, has eight fixed-width integer types, and every result of arithmetic on them is defined: an overflow or an out-of-range value is reported, never silently ignored. This page is the reference for the integer types, their operators and the number operations of the standard library.

Integer types

TypeWidthSmallest valueLargest value
i88 bits−128127
i1616 bits−32,76832,767
i3232 bits−2,147,483,6482,147,483,647
i6464 bits−9,223,372,036,854,775,8089,223,372,036,854,775,807
u88 bits0255
u1616 bits065,535
u3232 bits04,294,967,295
u6464 bits018,446,744,073,709,551,615
  • Signed types use two's complement, the same representation on every target.
  • Each width and sign is its own type. An i32 is never turned into an i64, or a u8 into a u16, without an explicit conversion.
  • bool is not a number, and a number is never a condition.

Literals

  • Integer literals are decimal: 0, 42, 1_000_000. A single _ may separate digits.
  • A literal takes the type its place expects: in let port: u16 = 8080; the literal is a u16. When nothing says otherwise, it is an i64.
  • A literal must fit the type it takes. let small: u8 = 300; is refused when you check your code, not when it runs.
  • A minus sign is an operator. The smallest signed value is still writable directly: -128 as an i8.

Arithmetic

The same rules apply in every build, with no difference between a debug build and a release build.

OperatorResultStops the program when
a + b, a - b, a * bThe exact result.The result does not fit the type.
a / bThe quotient, rounded toward zero: -7 / 2 is -3.b is zero, or a signed type's smallest value is divided by -1.
a % bThe remainder, with the sign of a: -7 % 2 is -1.b is zero, or a signed type's smallest value is divided by -1.
-aThe negated value. Signed types only.a is its type's smallest value.

Both sides of an operator must have the same type. Stopping the program is a panic: Errors and checked arithmetic describes what a panic does, and Results and errors how to report a failure your code expects instead.

Comparison and bits

  • ==, !=, <, <=, > and >= compare two integers of the same type and give a bool. Signed types compare as signed values, unsigned types as unsigned ones. Comparisons do not chain: write a < b && b < c.
  • &, |, ^ and ~ work on the exact bits of one integer type.
  • The shift count of << and >> is an unsigned integer of the same width as the value, and must be less than that width: a larger count stops the program. << stops the program when the result does not fit; >> rounds a signed value down and fills an unsigned one with zeros.

Wrapping and saturating operations

When you want a result other than a stop, you ask for it by name, at the place where you need it. The meaning of + never changes.

OperationsOn a result that does not fitTypes
Wrapping addition, subtraction, multiplication and negationThe result wraps around the type's range, as if counted modulo 2 to the power of the width.Every integer type.
Saturating addition, subtraction and multiplicationThe result stays at the type's smallest or largest value.Every integer type.
Saturating negationThe smallest value becomes the largest.Signed types.

The standard library has no wrapping or saturating division.

Checked conversions

Converting between integer types is always explicit. The standard library has one conversion for each of the eight target types. Each takes an integer of any type and returns Result<T, CastError>, where T is the target type:

  • Result::Ok(value) holds the same number in the new type;
  • Result::Err(CastError::OutOfRange) means the number does not fit, for example 300 into a u8 or -1 into a u64.

No conversion silently cuts off bits or changes a sign.

An example

Checked arithmetic stops the program on an overflow. When a large value is something your program expects, test for it first and return an error instead:

fn add_stock(on_hand: u16, delivered: u16) -> Result<u16, CapacityError> {
    if delivered > 65_535 - on_hand {
        return Result::Err(CapacityError::Full);
    }
    return Result::Ok(on_hand + delivered);
}

Outside this reference

This reference covers the integer types. These are outside it:

  • Floating-point and fixed-point numbers, and the machine-sized integers usize and isize.
  • Hexadecimal, binary and exponent literals.

Numerical arrays, complex numbers and linear algebra come from optional official packages, such as math/array and math/linalg. Scientific computing describes the scientific packages.