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
| Type | Width | Smallest value | Largest value |
|---|---|---|---|
i8 | 8 bits | −128 | 127 |
i16 | 16 bits | −32,768 | 32,767 |
i32 | 32 bits | −2,147,483,648 | 2,147,483,647 |
i64 | 64 bits | −9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
u8 | 8 bits | 0 | 255 |
u16 | 16 bits | 0 | 65,535 |
u32 | 32 bits | 0 | 4,294,967,295 |
u64 | 64 bits | 0 | 18,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
i32is never turned into ani64, or au8into au16, without an explicit conversion. boolis 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 au16. When nothing says otherwise, it is ani64. - 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:
-128as ani8.
Arithmetic
The same rules apply in every build, with no difference between a debug build and a release build.
| Operator | Result | Stops the program when |
|---|---|---|
a + b, a - b, a * b | The exact result. | The result does not fit the type. |
a / b | The quotient, rounded toward zero: -7 / 2 is -3. | b is zero, or a signed type's smallest value is divided by -1. |
a % b | The remainder, with the sign of a: -7 % 2 is -1. | b is zero, or a signed type's smallest value is divided by -1. |
-a | The 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 abool. Signed types compare as signed values, unsigned types as unsigned ones. Comparisons do not chain: writea < 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.
| Operations | On a result that does not fit | Types |
|---|---|---|
| Wrapping addition, subtraction, multiplication and negation | The 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 multiplication | The result stays at the type's smallest or largest value. | Every integer type. |
| Saturating negation | The 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 example300into au8or-1into au64.
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
usizeandisize. - 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.