tomo/docs/integers.md

395 lines
8.6 KiB
Markdown
Raw Normal View History

2024-08-18 13:51:25 -07:00
# Integers
Tomo has five types of integers:
- `Int`: the default integer type, which uses an efficient tagged 29-bit
integer value for small numbers, and falls back to a bigint implementation
when values are too large to fit in 29-bits. The bigint implementation uses
the GNU MP library. These integers are fast for small numbers and guaranteed
to always be correct and never overflow.
- `Int8`/`Int16`/`Int32`/`Int64`: Fixed-size integers that take up `N` bits.
These integers must be explicitly constructed using their type name (e.g.
`Int64(5)`) and are subject to overflowing on arithmetic operations. If an
overflow occurs, a runtime error will be raised.
- In cases where it is possible to infer that an integer literal should be
used as a fixed-size integer, the literal will be converted at compile time
to the appropriate fixed-size integer type and checked to ensure that it
can fit in the needed size. For example, if you declare a variable as
`x := Int64(0)` and later do `x + 1`, it's inferred that the `1` is a 64-bit
integer literal.
Runtime conversion between integer types (casting) can be done explicitly by
calling the target type as a function: `Int32(x)`. For fixed-width types, the
conversion function also accepts a second parameter, `truncate`. If `truncate`
is `no` (the default), conversion will create a runtime error if the value is
too large to fit in the target type. If `truncate` is `yes`, then the resulting
value will be a truncated form of the input value.
2024-08-18 13:51:25 -07:00
Integers support the standard math operations (`x+y`, `x-y`, `x*y`, `x/y`) as
well as powers/exponentiation (`x^y`), modulus (`x mod y` and `x mod1 y`), and
bitwise operations: `x and y`, `x or y`, `x xor y`, `x << y`, `x >> y`, `x >>>
y` (unsigned right shift), and `x <<< y` (unsighted left shift). The operators
`and`, `or`, and `xor` are _bitwise_, not logical operators.
2024-08-18 13:51:25 -07:00
# Integer Literals
The simplest form of integer literal is a string of digits, which is inferred
to have type `Int` (unbounded size).
```tomo
>>> 123456789012345678901234567890
= 123456789012345678901234567890 : Int
```
Underscores may also be used to visually break up the integer for readability:
```tomo
a_million := 1_000_000
```
Hexadecimal, octal, and binary integer literals are also supported:
```tomo
hex := 0x123F
octal := 0o644
binary := 0b10101
```
For fixed-sized integers, use the type's name as a constructor:
```tomo
my_int64 := Int64(12345)
my_int32 := Int32(12345)
my_int16 := Int32(12345)
my_int8 := Int32(123)
```
A compiler error will be raised if you attempt to construct a value that cannot
fit in the specified integer size (e.g. `Int8(99999)`).
2024-08-18 13:51:25 -07:00
# Integer Functions
Each integer type has its own version of the following functions. Functions
can be called either on the type itself: `Int.sqrt(x)` or as a method call:
`x:sqrt()`. Method call syntax is preferred.
## `format`
**Description:**
Formats an integer as a string with a specified number of digits.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func format(i: Int, digits: Int = 0 -> Text)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `i`: The integer to be formatted.
- `digits`: The minimum number of digits to which the integer should be padded. Default is `0`.
**Returns:**
A string representation of the integer, padded to the specified number of digits.
**Example:**
```tomo
>> 42:format(digits=5)
= "00042"
```
---
## `hex`
**Description:**
Converts an integer to its hexadecimal representation.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func hex(i: Int, digits: Int = 0, uppercase: Bool = yes, prefix: Bool = yes -> Text)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `i`: The integer to be converted.
- `digits`: The minimum number of digits in the output string. Default is `0`.
- `uppercase`: Whether to use uppercase letters for hexadecimal digits. Default is `yes`.
- `prefix`: Whether to include a "0x" prefix. Default is `yes`.
**Returns:**
The hexadecimal string representation of the integer.
**Example:**
```tomo
>> 255:hex(digits=4, uppercase=yes, prefix=yes)
= "0x00FF"
```
---
## `octal`
**Description:**
Converts an integer to its octal representation.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func octal(i: Int, digits: Int = 0, prefix: Bool = yes -> Text)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `i`: The integer to be converted.
- `digits`: The minimum number of digits in the output string. Default is `0`.
- `prefix`: Whether to include a "0o" prefix. Default is `yes`.
**Returns:**
The octal string representation of the integer.
**Example:**
```tomo
>> 64:octal(digits=4, prefix=yes)
= "0o0100"
```
---
2024-11-09 12:11:11 -08:00
## `parse`
2024-08-18 13:51:25 -07:00
**Description:**
Converts a text representation of an integer into an integer.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
2024-11-09 12:11:11 -08:00
func parse(text: Text -> Int?)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `text`: The text containing the integer.
2024-08-18 13:51:25 -07:00
**Returns:**
The integer represented by the text. If the given text contains a value outside
of the representable range or if the entire text can't be parsed as an integer,
2024-11-24 13:18:21 -08:00
`NONE` will be returned.
2024-08-18 13:51:25 -07:00
**Example:**
```tomo
2024-11-09 12:11:11 -08:00
>> Int.parse("123")
= 123 : Int?
2024-11-09 12:11:11 -08:00
>> Int.parse("0xFF")
= 255 : Int?
# Can't parse:
2024-11-09 12:11:11 -08:00
>> Int.parse("asdf")
2024-11-24 13:18:21 -08:00
= NONE : Int?
# Outside valid range:
2024-11-09 12:11:11 -08:00
>> Int8.parse("9999999")
2024-11-24 13:18:21 -08:00
= NONE : Int8?
2024-08-18 13:51:25 -07:00
```
---
## `to`
**Description:**
Creates an inclusive range of integers between the specified start and end values.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func to(from: Int, to: Int -> Range)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `from`: The starting value of the range.
- `to`: The ending value of the range.
**Returns:**
A range object representing all integers from `from` to `to` (inclusive).
**Example:**
```tomo
>> 1:to(5)
= Range(first=1, last=5, step=1)
```
---
## `abs`
**Description:**
Calculates the absolute value of an integer.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func abs(x: Int -> Int)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `x`: The integer whose absolute value is to be calculated.
**Returns:**
The absolute value of `x`.
**Example:**
```tomo
>> -10:abs()
= 10
```
---
## `sqrt`
**Description:**
Calculates the square root of an integer.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func sqrt(x: Int -> Int)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `x`: The integer whose square root is to be calculated.
**Returns:**
The integer part of the square root of `x`.
**Example:**
```tomo
>> 16:sqrt()
= 4
>> 17:sqrt()
= 4
```
---
## `is_prime`
**Description:**
Determines if an integer is a prime number.
**Note:**
This function is _probabilistic_. With the default arguments, the chances of
getting an incorrect answer are astronomically small (on the order of 10^(-30)).
See [the GNU MP docs](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp)
for more details.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func is_prime(x: Int, reps: Int = 50 -> Bool)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `x`: The integer to be checked.
- `reps`: The number of repetitions for primality tests. Default is `50`.
**Returns:**
`yes` if `x` is a prime number, `no` otherwise.
**Example:**
```tomo
>> 7:is_prime()
= yes
>> 6:is_prime()
= no
```
---
## `next_prime`
**Description:**
Finds the next prime number greater than the given integer.
**Note:**
This function is _probabilistic_, but the chances of getting an incorrect
answer are astronomically small (on the order of 10^(-30)).
See [the GNU MP docs](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp)
for more details.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func next_prime(x: Int -> Int)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `x`: The integer after which to find the next prime.
**Returns:**
The next prime number greater than `x`.
**Example:**
```tomo
2024-08-18 20:20:54 -07:00
>> 11:next_prime()
= 13
2024-08-18 13:51:25 -07:00
```
---
## `prev_prime`
**Description:**
Finds the previous prime number less than the given integer.
If there is no previous prime number (i.e. if a number less than `2` is
provided), then the function will create a runtime error.
**Note:**
This function is _probabilistic_, but the chances of getting an incorrect
answer are astronomically small (on the order of 10^(-30)).
See [the GNU MP docs](https://gmplib.org/manual/Number-Theoretic-Functions#index-mpz_005fprobab_005fprime_005fp)
for more details.
**Signature:**
2024-08-18 13:51:25 -07:00
```tomo
func prev_prime(x: Int -> Int)
2024-08-18 13:51:25 -07:00
```
**Parameters:**
- `x`: The integer before which to find the previous prime.
**Returns:**
The previous prime number less than `x`.
**Example:**
```tomo
2024-08-18 20:20:54 -07:00
>> 11:prev_prime()
= 7
```
---
## `clamped`
**Description:**
Returns the given number clamped between two values so that it is within
that range.
**Signature:**
2024-08-18 20:20:54 -07:00
```tomo
func clamped(x, low, high: Int -> Int)
2024-08-18 20:20:54 -07:00
```
**Parameters:**
- `x`: The integer to clamp.
- `low`: The lowest value the result can take.
- `high`: The highest value the result can take.
**Returns:**
The first argument clamped between the other two arguments.
**Example:**
```tomo
>> 2:clamped(5, 10)
= 5
2024-08-18 13:51:25 -07:00
```