aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--api/api.md100
-rw-r--r--api/integers.md22
-rw-r--r--api/integers.yaml22
-rw-r--r--api/nums.md78
-rw-r--r--api/nums.yaml79
-rw-r--r--lib/time/time_defs.h2
-rw-r--r--man/man3/tomo-Bool.parse.32
-rw-r--r--man/man3/tomo-Byte.hex.32
-rw-r--r--man/man3/tomo-Byte.is_between.32
-rw-r--r--man/man3/tomo-Byte.parse.32
-rw-r--r--man/man3/tomo-Byte.to.32
-rw-r--r--man/man3/tomo-Int.abs.32
-rw-r--r--man/man3/tomo-Int.choose.32
-rw-r--r--man/man3/tomo-Int.clamped.32
-rw-r--r--man/man3/tomo-Int.factorial.32
-rw-r--r--man/man3/tomo-Int.format.335
-rw-r--r--man/man3/tomo-Int.hex.32
-rw-r--r--man/man3/tomo-Int.is_between.32
-rw-r--r--man/man3/tomo-Int.is_prime.32
-rw-r--r--man/man3/tomo-Int.next_prime.32
-rw-r--r--man/man3/tomo-Int.octal.32
-rw-r--r--man/man3/tomo-Int.onward.32
-rw-r--r--man/man3/tomo-Int.parse.32
-rw-r--r--man/man3/tomo-Int.prev_prime.32
-rw-r--r--man/man3/tomo-Int.sqrt.32
-rw-r--r--man/man3/tomo-Int.to.32
-rw-r--r--man/man3/tomo-List.binary_search.32
-rw-r--r--man/man3/tomo-List.by.32
-rw-r--r--man/man3/tomo-List.clear.32
-rw-r--r--man/man3/tomo-List.counts.32
-rw-r--r--man/man3/tomo-List.find.32
-rw-r--r--man/man3/tomo-List.from.32
-rw-r--r--man/man3/tomo-List.has.32
-rw-r--r--man/man3/tomo-List.heap_pop.32
-rw-r--r--man/man3/tomo-List.heap_push.32
-rw-r--r--man/man3/tomo-List.heapify.32
-rw-r--r--man/man3/tomo-List.insert.32
-rw-r--r--man/man3/tomo-List.insert_all.32
-rw-r--r--man/man3/tomo-List.pop.32
-rw-r--r--man/man3/tomo-List.random.32
-rw-r--r--man/man3/tomo-List.remove_at.32
-rw-r--r--man/man3/tomo-List.remove_item.32
-rw-r--r--man/man3/tomo-List.reversed.32
-rw-r--r--man/man3/tomo-List.sample.32
-rw-r--r--man/man3/tomo-List.shuffle.32
-rw-r--r--man/man3/tomo-List.shuffled.32
-rw-r--r--man/man3/tomo-List.slice.32
-rw-r--r--man/man3/tomo-List.sort.32
-rw-r--r--man/man3/tomo-List.sorted.32
-rw-r--r--man/man3/tomo-List.to.32
-rw-r--r--man/man3/tomo-List.unique.32
-rw-r--r--man/man3/tomo-List.where.32
-rw-r--r--man/man3/tomo-Num.1_PI.32
-rw-r--r--man/man3/tomo-Num.2_PI.32
-rw-r--r--man/man3/tomo-Num.2_SQRTPI.32
-rw-r--r--man/man3/tomo-Num.E.32
-rw-r--r--man/man3/tomo-Num.INF.32
-rw-r--r--man/man3/tomo-Num.LN10.32
-rw-r--r--man/man3/tomo-Num.LN2.32
-rw-r--r--man/man3/tomo-Num.LOG2E.32
-rw-r--r--man/man3/tomo-Num.PI.32
-rw-r--r--man/man3/tomo-Num.PI_2.32
-rw-r--r--man/man3/tomo-Num.PI_4.32
-rw-r--r--man/man3/tomo-Num.SQRT1_2.32
-rw-r--r--man/man3/tomo-Num.SQRT2.32
-rw-r--r--man/man3/tomo-Num.TAU.32
-rw-r--r--man/man3/tomo-Num.abs.32
-rw-r--r--man/man3/tomo-Num.acos.32
-rw-r--r--man/man3/tomo-Num.acosh.32
-rw-r--r--man/man3/tomo-Num.asin.32
-rw-r--r--man/man3/tomo-Num.asinh.32
-rw-r--r--man/man3/tomo-Num.atan.32
-rw-r--r--man/man3/tomo-Num.atan2.32
-rw-r--r--man/man3/tomo-Num.atanh.32
-rw-r--r--man/man3/tomo-Num.cbrt.32
-rw-r--r--man/man3/tomo-Num.ceil.32
-rw-r--r--man/man3/tomo-Num.clamped.32
-rw-r--r--man/man3/tomo-Num.copysign.32
-rw-r--r--man/man3/tomo-Num.cos.32
-rw-r--r--man/man3/tomo-Num.cosh.32
-rw-r--r--man/man3/tomo-Num.erf.32
-rw-r--r--man/man3/tomo-Num.erfc.32
-rw-r--r--man/man3/tomo-Num.exp.32
-rw-r--r--man/man3/tomo-Num.exp2.32
-rw-r--r--man/man3/tomo-Num.expm1.32
-rw-r--r--man/man3/tomo-Num.fdim.32
-rw-r--r--man/man3/tomo-Num.floor.32
-rw-r--r--man/man3/tomo-Num.format.335
-rw-r--r--man/man3/tomo-Num.hypot.32
-rw-r--r--man/man3/tomo-Num.is_between.32
-rw-r--r--man/man3/tomo-Num.isfinite.32
-rw-r--r--man/man3/tomo-Num.isinf.32
-rw-r--r--man/man3/tomo-Num.j0.32
-rw-r--r--man/man3/tomo-Num.j1.32
-rw-r--r--man/man3/tomo-Num.log.32
-rw-r--r--man/man3/tomo-Num.log10.32
-rw-r--r--man/man3/tomo-Num.log1p.32
-rw-r--r--man/man3/tomo-Num.log2.32
-rw-r--r--man/man3/tomo-Num.logb.32
-rw-r--r--man/man3/tomo-Num.mix.32
-rw-r--r--man/man3/tomo-Num.near.32
-rw-r--r--man/man3/tomo-Num.nextafter.32
-rw-r--r--man/man3/tomo-Num.parse.32
-rw-r--r--man/man3/tomo-Num.percent.310
-rw-r--r--man/man3/tomo-Num.rint.32
-rw-r--r--man/man3/tomo-Num.round.32
-rw-r--r--man/man3/tomo-Num.scientific.335
-rw-r--r--man/man3/tomo-Num.significand.32
-rw-r--r--man/man3/tomo-Num.sin.32
-rw-r--r--man/man3/tomo-Num.sinh.32
-rw-r--r--man/man3/tomo-Num.sqrt.32
-rw-r--r--man/man3/tomo-Num.tan.32
-rw-r--r--man/man3/tomo-Num.tanh.32
-rw-r--r--man/man3/tomo-Num.tgamma.32
-rw-r--r--man/man3/tomo-Num.trunc.32
-rw-r--r--man/man3/tomo-Num.with_precision.339
-rw-r--r--man/man3/tomo-Num.y0.32
-rw-r--r--man/man3/tomo-Num.y1.32
-rw-r--r--man/man3/tomo-Path.accessed.32
-rw-r--r--man/man3/tomo-Path.append.32
-rw-r--r--man/man3/tomo-Path.append_bytes.32
-rw-r--r--man/man3/tomo-Path.base_name.32
-rw-r--r--man/man3/tomo-Path.by_line.32
-rw-r--r--man/man3/tomo-Path.can_execute.32
-rw-r--r--man/man3/tomo-Path.can_read.32
-rw-r--r--man/man3/tomo-Path.can_write.32
-rw-r--r--man/man3/tomo-Path.changed.32
-rw-r--r--man/man3/tomo-Path.child.32
-rw-r--r--man/man3/tomo-Path.children.32
-rw-r--r--man/man3/tomo-Path.create_directory.32
-rw-r--r--man/man3/tomo-Path.current_dir.32
-rw-r--r--man/man3/tomo-Path.exists.32
-rw-r--r--man/man3/tomo-Path.expand_home.32
-rw-r--r--man/man3/tomo-Path.extension.32
-rw-r--r--man/man3/tomo-Path.files.32
-rw-r--r--man/man3/tomo-Path.from_components.32
-rw-r--r--man/man3/tomo-Path.glob.32
-rw-r--r--man/man3/tomo-Path.group.32
-rw-r--r--man/man3/tomo-Path.is_directory.32
-rw-r--r--man/man3/tomo-Path.is_file.32
-rw-r--r--man/man3/tomo-Path.is_socket.32
-rw-r--r--man/man3/tomo-Path.is_symlink.32
-rw-r--r--man/man3/tomo-Path.modified.32
-rw-r--r--man/man3/tomo-Path.owner.32
-rw-r--r--man/man3/tomo-Path.parent.32
-rw-r--r--man/man3/tomo-Path.read.32
-rw-r--r--man/man3/tomo-Path.read_bytes.32
-rw-r--r--man/man3/tomo-Path.relative_to.32
-rw-r--r--man/man3/tomo-Path.remove.32
-rw-r--r--man/man3/tomo-Path.resolved.32
-rw-r--r--man/man3/tomo-Path.set_owner.32
-rw-r--r--man/man3/tomo-Path.subdirectories.32
-rw-r--r--man/man3/tomo-Path.unique_directory.32
-rw-r--r--man/man3/tomo-Path.write.32
-rw-r--r--man/man3/tomo-Path.write_bytes.32
-rw-r--r--man/man3/tomo-Path.write_unique.32
-rw-r--r--man/man3/tomo-Path.write_unique_bytes.32
-rw-r--r--man/man3/tomo-Set.add.32
-rw-r--r--man/man3/tomo-Set.add_all.32
-rw-r--r--man/man3/tomo-Set.clear.32
-rw-r--r--man/man3/tomo-Set.has.32
-rw-r--r--man/man3/tomo-Set.is_subset_of.32
-rw-r--r--man/man3/tomo-Set.is_superset_of.32
-rw-r--r--man/man3/tomo-Set.overlap.32
-rw-r--r--man/man3/tomo-Set.remove.32
-rw-r--r--man/man3/tomo-Set.remove_all.32
-rw-r--r--man/man3/tomo-Set.with.32
-rw-r--r--man/man3/tomo-Set.without.32
-rw-r--r--man/man3/tomo-Table.clear.32
-rw-r--r--man/man3/tomo-Table.get.32
-rw-r--r--man/man3/tomo-Table.get_or_set.32
-rw-r--r--man/man3/tomo-Table.has.32
-rw-r--r--man/man3/tomo-Table.remove.32
-rw-r--r--man/man3/tomo-Table.set.32
-rw-r--r--man/man3/tomo-Text.as_c_string.32
-rw-r--r--man/man3/tomo-Text.at.32
-rw-r--r--man/man3/tomo-Text.by_line.32
-rw-r--r--man/man3/tomo-Text.by_split.32
-rw-r--r--man/man3/tomo-Text.by_split_any.32
-rw-r--r--man/man3/tomo-Text.bytes.32
-rw-r--r--man/man3/tomo-Text.caseless_equals.32
-rw-r--r--man/man3/tomo-Text.codepoint_names.32
-rw-r--r--man/man3/tomo-Text.ends_with.32
-rw-r--r--man/man3/tomo-Text.from.32
-rw-r--r--man/man3/tomo-Text.from_bytes.32
-rw-r--r--man/man3/tomo-Text.from_c_string.32
-rw-r--r--man/man3/tomo-Text.from_codepoint_names.32
-rw-r--r--man/man3/tomo-Text.from_codepoints.32
-rw-r--r--man/man3/tomo-Text.has.32
-rw-r--r--man/man3/tomo-Text.join.32
-rw-r--r--man/man3/tomo-Text.left_pad.32
-rw-r--r--man/man3/tomo-Text.lines.32
-rw-r--r--man/man3/tomo-Text.lower.32
-rw-r--r--man/man3/tomo-Text.middle_pad.32
-rw-r--r--man/man3/tomo-Text.quoted.32
-rw-r--r--man/man3/tomo-Text.repeat.32
-rw-r--r--man/man3/tomo-Text.replace.32
-rw-r--r--man/man3/tomo-Text.reversed.32
-rw-r--r--man/man3/tomo-Text.right_pad.32
-rw-r--r--man/man3/tomo-Text.slice.32
-rw-r--r--man/man3/tomo-Text.split.32
-rw-r--r--man/man3/tomo-Text.split_any.32
-rw-r--r--man/man3/tomo-Text.starts_with.32
-rw-r--r--man/man3/tomo-Text.title.32
-rw-r--r--man/man3/tomo-Text.to.32
-rw-r--r--man/man3/tomo-Text.translate.32
-rw-r--r--man/man3/tomo-Text.trim.32
-rw-r--r--man/man3/tomo-Text.upper.32
-rw-r--r--man/man3/tomo-Text.utf32_codepoints.32
-rw-r--r--man/man3/tomo-Text.width.32
-rw-r--r--man/man3/tomo-Text.without_prefix.32
-rw-r--r--man/man3/tomo-Text.without_suffix.32
-rw-r--r--man/man3/tomo-USE_COLOR.32
-rw-r--r--man/man3/tomo-ask.32
-rw-r--r--man/man3/tomo-exit.32
-rw-r--r--man/man3/tomo-fail.32
-rw-r--r--man/man3/tomo-getenv.32
-rw-r--r--man/man3/tomo-print.32
-rw-r--r--man/man3/tomo-say.32
-rw-r--r--man/man3/tomo-setenv.32
-rw-r--r--man/man3/tomo-sleep.32
-rwxr-xr-xscripts/mandoc_gen.py1
-rw-r--r--src/environment.c17
-rw-r--r--src/stdlib/bytes.c32
-rw-r--r--src/stdlib/c_strings.c5
-rw-r--r--src/stdlib/c_strings.h2
-rw-r--r--src/stdlib/enums.c6
-rw-r--r--src/stdlib/files.c28
-rw-r--r--src/stdlib/fpconv.c341
-rw-r--r--src/stdlib/fpconv.h36
-rw-r--r--src/stdlib/functiontype.c2
-rw-r--r--src/stdlib/integers.c76
-rw-r--r--src/stdlib/integers.h2
-rw-r--r--src/stdlib/memory.c3
-rw-r--r--src/stdlib/metamethods.c2
-rw-r--r--src/stdlib/nums.c56
-rw-r--r--src/stdlib/nums.h10
-rw-r--r--src/stdlib/pointers.c9
-rw-r--r--src/stdlib/powers.h91
-rw-r--r--src/stdlib/print.c123
-rw-r--r--src/stdlib/print.h53
-rw-r--r--src/stdlib/stacktrace.c28
-rw-r--r--src/stdlib/stdlib.c23
-rw-r--r--src/stdlib/structs.c8
-rw-r--r--src/stdlib/tables.c27
-rw-r--r--src/stdlib/text.c55
-rw-r--r--src/stdlib/text.h2
-rw-r--r--src/tomo.c3
-rw-r--r--test/integers.tm4
-rw-r--r--test/nums.tm4
251 files changed, 1144 insertions, 785 deletions
diff --git a/Makefile b/Makefile
index a9d45317..84c0f134 100644
--- a/Makefile
+++ b/Makefile
@@ -144,7 +144,8 @@ api-docs: $(API_MD) api/api.md
.PHONY: manpages
manpages: $(API_YAML) man/man1/tomo.1
- ./scripts/mandoc_gen.py $^
+ rm -f man/man3/*
+ ./scripts/mandoc_gen.py $(API_YAML)
man/man1/tomo.1: docs/tomo.1.md
pandoc --lua-filter=docs/.pandoc/bold-code.lua -s $< -t man -o $@
diff --git a/api/api.md b/api/api.md
index 56105498..527708ad 100644
--- a/api/api.md
+++ b/api/api.md
@@ -402,28 +402,6 @@ n | `Int` | The integer to compute the factorial of. | -
= 3628800
```
-## Int.format
-
-```tomo
-Int.format : func(i: Int, digits: Int = 0 -> Text)
-```
-
-Formats an integer as a string with a specified number of digits.
-
-Argument | Type | Description | Default
----------|------|-------------|---------
-i | `Int` | The integer to be formatted. | -
-digits | `Int` | The minimum number of digits to which the integer should be padded. | `0`
-
-**Return:** A string representation of the integer, padded to the specified number of digits.
-
-
-**Example:**
-```tomo
->> (42).format(digits=5)
-= "00042"
-
-```
## Int.hex
```tomo
@@ -1890,28 +1868,6 @@ x | `Num` | The number to be rounded down. | -
= 3
```
-## Num.format
-
-```tomo
-Num.format : func(n: Num, precision: Int = 0 -> Text)
-```
-
-Formats a number as a text with a specified precision.
-
-Argument | Type | Description | Default
----------|------|-------------|---------
-n | `Num` | The number to be formatted. | -
-precision | `Int` | The number of decimal places. Default is `0`. | `0`
-
-**Return:** A text representation of the number with the specified precision.
-
-
-**Example:**
-```tomo
->> (3.14159).format(precision=2)
-= "3.14"
-
-```
## Num.hypot
```tomo
@@ -2257,7 +2213,7 @@ text | `Text` | The text containing the number. | -
## Num.percent
```tomo
-Num.percent : func(n: Num, precision: Int = 0 -> Text)
+Num.percent : func(n: Num, precision: Num = 0.01 -> Text)
```
Convert a number into a percentage text with a percent sign.
@@ -2265,7 +2221,7 @@ Convert a number into a percentage text with a percent sign.
Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to be converted to a percent. | -
-precision | `Int` | The number of decimal places. Default is `0`. | `0`
+precision | `Num` | Round the percentage to this precision level. | `0.01`
**Return:** A text representation of the number as a percentage with a percent sign.
@@ -2276,6 +2232,10 @@ precision | `Int` | The number of decimal places. Default is `0`. | `0`
= "50%"
>> (1./3.).percent(2)
= "33.33%"
+>> (1./3.).percent(2, precision=0.0001)
+= "33.3333%"
+>> (1./3.).percent(2, precision=10.)
+= "30%"
```
## Num.rint
@@ -2324,28 +2284,6 @@ x | `Num` | The number to be rounded. | -
= 3
```
-## Num.scientific
-
-```tomo
-Num.scientific : func(n: Num, precision: Int = 0 -> Text)
-```
-
-Formats a number in scientific notation with a specified precision.
-
-Argument | Type | Description | Default
----------|------|-------------|---------
-n | `Num` | The number to be formatted. | -
-precision | `Int` | The number of decimal places. Default is `0`. | `0`
-
-**Return:** A text representation of the number in scientific notation with the specified precision.
-
-
-**Example:**
-```tomo
->> (12345.6789).scientific(precision=2)
-= "1.23e+04"
-
-```
## Num.significand
```tomo
@@ -2516,6 +2454,32 @@ x | `Num` | The number to be truncated. | -
= -3
```
+## Num.with_precision
+
+```tomo
+Num.with_precision : func(n: Num, precision: Num -> Num)
+```
+
+Round a number to the given precision level (specified as `10`, `.1`, `.001` etc).
+
+Argument | Type | Description | Default
+---------|------|-------------|---------
+n | `Num` | The number to be rounded to a given precision. | -
+precision | `Num` | The precision to which the number should be rounded. | -
+
+**Return:** The number, rounded to the given precision level.
+
+
+**Example:**
+```tomo
+>> (0.1234567).with_precision(0.01)
+= 0.12
+>> (123456.).with_precision(100)
+= 123500
+>> (1234567.).with_precision(5)
+= 1234565
+
+```
## Num.y0
```tomo
diff --git a/api/integers.md b/api/integers.md
index d79812df..0865e93f 100644
--- a/api/integers.md
+++ b/api/integers.md
@@ -90,28 +90,6 @@ n | `Int` | The integer to compute the factorial of. | -
= 3628800
```
-## Int.format
-
-```tomo
-Int.format : func(i: Int, digits: Int = 0 -> Text)
-```
-
-Formats an integer as a string with a specified number of digits.
-
-Argument | Type | Description | Default
----------|------|-------------|---------
-i | `Int` | The integer to be formatted. | -
-digits | `Int` | The minimum number of digits to which the integer should be padded. | `0`
-
-**Return:** A string representation of the integer, padded to the specified number of digits.
-
-
-**Example:**
-```tomo
->> (42).format(digits=5)
-= "00042"
-
-```
## Int.hex
```tomo
diff --git a/api/integers.yaml b/api/integers.yaml
index 4e5ec46c..f927c75f 100644
--- a/api/integers.yaml
+++ b/api/integers.yaml
@@ -82,28 +82,6 @@ Int.factorial:
>> (10).factorial()
= 3628800
-Int.format:
- short: text formatting
- description: >
- Formats an integer as a string with a specified number of digits.
- return:
- type: 'Text'
- description: >
- A string representation of the integer, padded to the specified number of digits.
- args:
- i:
- type: 'Int'
- description: >
- The integer to be formatted.
- digits:
- type: 'Int'
- default: '0'
- description: >
- The minimum number of digits to which the integer should be padded.
- example: |
- >> (42).format(digits=5)
- = "00042"
-
Int.hex:
short: convert to hexidecimal
description: >
diff --git a/api/nums.md b/api/nums.md
index e42329f9..471a7739 100644
--- a/api/nums.md
+++ b/api/nums.md
@@ -563,28 +563,6 @@ x | `Num` | The number to be rounded down. | -
= 3
```
-## Num.format
-
-```tomo
-Num.format : func(n: Num, precision: Int = 0 -> Text)
-```
-
-Formats a number as a text with a specified precision.
-
-Argument | Type | Description | Default
----------|------|-------------|---------
-n | `Num` | The number to be formatted. | -
-precision | `Int` | The number of decimal places. Default is `0`. | `0`
-
-**Return:** A text representation of the number with the specified precision.
-
-
-**Example:**
-```tomo
->> (3.14159).format(precision=2)
-= "3.14"
-
-```
## Num.hypot
```tomo
@@ -930,7 +908,7 @@ text | `Text` | The text containing the number. | -
## Num.percent
```tomo
-Num.percent : func(n: Num, precision: Int = 0 -> Text)
+Num.percent : func(n: Num, precision: Num = 0.01 -> Text)
```
Convert a number into a percentage text with a percent sign.
@@ -938,7 +916,7 @@ Convert a number into a percentage text with a percent sign.
Argument | Type | Description | Default
---------|------|-------------|---------
n | `Num` | The number to be converted to a percent. | -
-precision | `Int` | The number of decimal places. Default is `0`. | `0`
+precision | `Num` | Round the percentage to this precision level. | `0.01`
**Return:** A text representation of the number as a percentage with a percent sign.
@@ -949,6 +927,10 @@ precision | `Int` | The number of decimal places. Default is `0`. | `0`
= "50%"
>> (1./3.).percent(2)
= "33.33%"
+>> (1./3.).percent(2, precision=0.0001)
+= "33.3333%"
+>> (1./3.).percent(2, precision=10.)
+= "30%"
```
## Num.rint
@@ -997,28 +979,6 @@ x | `Num` | The number to be rounded. | -
= 3
```
-## Num.scientific
-
-```tomo
-Num.scientific : func(n: Num, precision: Int = 0 -> Text)
-```
-
-Formats a number in scientific notation with a specified precision.
-
-Argument | Type | Description | Default
----------|------|-------------|---------
-n | `Num` | The number to be formatted. | -
-precision | `Int` | The number of decimal places. Default is `0`. | `0`
-
-**Return:** A text representation of the number in scientific notation with the specified precision.
-
-
-**Example:**
-```tomo
->> (12345.6789).scientific(precision=2)
-= "1.23e+04"
-
-```
## Num.significand
```tomo
@@ -1189,6 +1149,32 @@ x | `Num` | The number to be truncated. | -
= -3
```
+## Num.with_precision
+
+```tomo
+Num.with_precision : func(n: Num, precision: Num -> Num)
+```
+
+Round a number to the given precision level (specified as `10`, `.1`, `.001` etc).
+
+Argument | Type | Description | Default
+---------|------|-------------|---------
+n | `Num` | The number to be rounded to a given precision. | -
+precision | `Num` | The precision to which the number should be rounded. | -
+
+**Return:** The number, rounded to the given precision level.
+
+
+**Example:**
+```tomo
+>> (0.1234567).with_precision(0.01)
+= 0.12
+>> (123456.).with_precision(100)
+= 123500
+>> (1234567.).with_precision(5)
+= 1234565
+
+```
## Num.y0
```tomo
diff --git a/api/nums.yaml b/api/nums.yaml
index 37b2c7c5..e666a0d6 100644
--- a/api/nums.yaml
+++ b/api/nums.yaml
@@ -378,28 +378,6 @@ Num.floor:
>> (3.7).floor()
= 3
-Num.format:
- short: convert a number to text
- description: >
- Formats a number as a text with a specified precision.
- return:
- type: 'Text'
- description: >
- A text representation of the number with the specified precision.
- args:
- n:
- type: 'Num'
- description: >
- The number to be formatted.
- precision:
- type: 'Int'
- default: '0'
- description: >
- The number of decimal places. Default is `0`.
- example: |
- >> (3.14159).format(precision=2)
- = "3.14"
-
Num.hypot:
short: Euclidean distance function
description: >
@@ -728,15 +706,44 @@ Num.percent:
description: >
The number to be converted to a percent.
precision:
- type: 'Int'
- default: '0'
+ type: 'Num'
+ default: '0.01'
description: >
- The number of decimal places. Default is `0`.
+ Round the percentage to this precision level.
example: |
>> (0.5).percent()
= "50%"
>> (1./3.).percent(2)
= "33.33%"
+ >> (1./3.).percent(2, precision=0.0001)
+ = "33.3333%"
+ >> (1./3.).percent(2, precision=10.)
+ = "30%"
+
+Num.with_precision:
+ short: round to a given precision
+ description: >
+ Round a number to the given precision level (specified as `10`, `.1`, `.001` etc).
+ return:
+ type: 'Num'
+ description: >
+ The number, rounded to the given precision level.
+ args:
+ n:
+ type: 'Num'
+ description: >
+ The number to be rounded to a given precision.
+ precision:
+ type: 'Num'
+ description: >
+ The precision to which the number should be rounded.
+ example: |
+ >> (0.1234567).with_precision(0.01)
+ = 0.12
+ >> (123456.).with_precision(100)
+ = 123500
+ >> (1234567.).with_precision(5)
+ = 1234565
Num.rint:
short: round to nearest integer
@@ -776,28 +783,6 @@ Num.round:
>> (2.7).round()
= 3
-Num.scientific:
- short: format in scientific notation
- description: >
- Formats a number in scientific notation with a specified precision.
- return:
- type: 'Text'
- description: >
- A text representation of the number in scientific notation with the specified precision.
- args:
- n:
- type: 'Num'
- description: >
- The number to be formatted.
- precision:
- type: 'Int'
- default: '0'
- description: >
- The number of decimal places. Default is `0`.
- example: |
- >> (12345.6789).scientific(precision=2)
- = "1.23e+04"
-
Num.significand:
short: get mantissa
description: >
diff --git a/lib/time/time_defs.h b/lib/time/time_defs.h
index fd8fd4f3..7afb9c16 100644
--- a/lib/time/time_defs.h
+++ b/lib/time/time_defs.h
@@ -10,7 +10,7 @@ static INLINE Text_t num_format(long n, const char *unit)
{
if (n == 0)
return Text("now");
- return Text$format((n == 1 || n == -1) ? "%ld %s %s" : "%ld %ss %s", n < 0 ? -n : n, unit, n < 0 ? "ago" : "later");
+ return Text$from_str(String(labs(n), " ", unit, (n == -1 || n == 1) ? "" : "s", n <= 0 ? " ago" : " later"));
}
static void set_local_timezone(Text_t tz)
diff --git a/man/man3/tomo-Bool.parse.3 b/man/man3/tomo-Bool.parse.3
index 0787ecfd..e7ff9862 100644
--- a/man/man3/tomo-Bool.parse.3
+++ b/man/man3/tomo-Bool.parse.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Bool.parse 3 2025-04-21 "Tomo man-pages"
+.TH Bool.parse 3 2025-04-27 "Tomo man-pages"
.SH NAME
Bool.parse \- parse into boolean
.SH LIBRARY
diff --git a/man/man3/tomo-Byte.hex.3 b/man/man3/tomo-Byte.hex.3
index 0252f339..37c2d7a7 100644
--- a/man/man3/tomo-Byte.hex.3
+++ b/man/man3/tomo-Byte.hex.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Byte.hex 3 2025-04-21 "Tomo man-pages"
+.TH Byte.hex 3 2025-04-27 "Tomo man-pages"
.SH NAME
Byte.hex \- convert to hexidecimal
.SH LIBRARY
diff --git a/man/man3/tomo-Byte.is_between.3 b/man/man3/tomo-Byte.is_between.3
index 1860b524..189a282d 100644
--- a/man/man3/tomo-Byte.is_between.3
+++ b/man/man3/tomo-Byte.is_between.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Byte.is_between 3 2025-04-21 "Tomo man-pages"
+.TH Byte.is_between 3 2025-04-27 "Tomo man-pages"
.SH NAME
Byte.is_between \- test if inside a range
.SH LIBRARY
diff --git a/man/man3/tomo-Byte.parse.3 b/man/man3/tomo-Byte.parse.3
index 774ac07c..dc714073 100644
--- a/man/man3/tomo-Byte.parse.3
+++ b/man/man3/tomo-Byte.parse.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Byte.parse 3 2025-04-21 "Tomo man-pages"
+.TH Byte.parse 3 2025-04-27 "Tomo man-pages"
.SH NAME
Byte.parse \- convert text to a byte
.SH LIBRARY
diff --git a/man/man3/tomo-Byte.to.3 b/man/man3/tomo-Byte.to.3
index 4120495a..69228ba0 100644
--- a/man/man3/tomo-Byte.to.3
+++ b/man/man3/tomo-Byte.to.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Byte.to 3 2025-04-21 "Tomo man-pages"
+.TH Byte.to 3 2025-04-27 "Tomo man-pages"
.SH NAME
Byte.to \- iterate over a range of bytes
.SH LIBRARY
diff --git a/man/man3/tomo-Int.abs.3 b/man/man3/tomo-Int.abs.3
index ccf95617..39ae6416 100644
--- a/man/man3/tomo-Int.abs.3
+++ b/man/man3/tomo-Int.abs.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.abs 3 2025-04-21 "Tomo man-pages"
+.TH Int.abs 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.abs \- absolute value
.SH LIBRARY
diff --git a/man/man3/tomo-Int.choose.3 b/man/man3/tomo-Int.choose.3
index 9e268cb2..569bdc76 100644
--- a/man/man3/tomo-Int.choose.3
+++ b/man/man3/tomo-Int.choose.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.choose 3 2025-04-21 "Tomo man-pages"
+.TH Int.choose 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.choose \- binomial coefficient
.SH LIBRARY
diff --git a/man/man3/tomo-Int.clamped.3 b/man/man3/tomo-Int.clamped.3
index 62561e08..883a147a 100644
--- a/man/man3/tomo-Int.clamped.3
+++ b/man/man3/tomo-Int.clamped.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.clamped 3 2025-04-21 "Tomo man-pages"
+.TH Int.clamped 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.clamped \- clamp an integer
.SH LIBRARY
diff --git a/man/man3/tomo-Int.factorial.3 b/man/man3/tomo-Int.factorial.3
index d4137c4b..2fe1a880 100644
--- a/man/man3/tomo-Int.factorial.3
+++ b/man/man3/tomo-Int.factorial.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.factorial 3 2025-04-21 "Tomo man-pages"
+.TH Int.factorial 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.factorial \- factorial
.SH LIBRARY
diff --git a/man/man3/tomo-Int.format.3 b/man/man3/tomo-Int.format.3
deleted file mode 100644
index ce3472fe..00000000
--- a/man/man3/tomo-Int.format.3
+++ /dev/null
@@ -1,35 +0,0 @@
-'\" t
-.\" Copyright (c) 2025 Bruce Hill
-.\" All rights reserved.
-.\"
-.TH Int.format 3 2025-04-21 "Tomo man-pages"
-.SH NAME
-Int.format \- text formatting
-.SH LIBRARY
-Tomo Standard Library
-.SH SYNOPSIS
-.nf
-.BI Int.format\ :\ func(i:\ Int,\ digits:\ Int\ =\ 0\ ->\ Text)
-.fi
-.SH DESCRIPTION
-Formats an integer as a string with a specified number of digits.
-
-
-.SH ARGUMENTS
-
-.TS
-allbox;
-lb lb lbx lb
-l l l l.
-Name Type Description Default
-i Int The integer to be formatted. -
-digits Int The minimum number of digits to which the integer should be padded. 0
-.TE
-.SH RETURN
-A string representation of the integer, padded to the specified number of digits.
-
-.SH EXAMPLES
-.EX
->> (42).format(digits=5)
-= "00042"
-.EE
diff --git a/man/man3/tomo-Int.hex.3 b/man/man3/tomo-Int.hex.3
index 35c00bf2..b60ae256 100644
--- a/man/man3/tomo-Int.hex.3
+++ b/man/man3/tomo-Int.hex.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.hex 3 2025-04-21 "Tomo man-pages"
+.TH Int.hex 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.hex \- convert to hexidecimal
.SH LIBRARY
diff --git a/man/man3/tomo-Int.is_between.3 b/man/man3/tomo-Int.is_between.3
index 1bcd9682..3030d593 100644
--- a/man/man3/tomo-Int.is_between.3
+++ b/man/man3/tomo-Int.is_between.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.is_between 3 2025-04-21 "Tomo man-pages"
+.TH Int.is_between 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.is_between \- test if an int is in a range
.SH LIBRARY
diff --git a/man/man3/tomo-Int.is_prime.3 b/man/man3/tomo-Int.is_prime.3
index 7ed8c67d..2577d624 100644
--- a/man/man3/tomo-Int.is_prime.3
+++ b/man/man3/tomo-Int.is_prime.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.is_prime 3 2025-04-21 "Tomo man-pages"
+.TH Int.is_prime 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.is_prime \- check if an integer is prime
.SH LIBRARY
diff --git a/man/man3/tomo-Int.next_prime.3 b/man/man3/tomo-Int.next_prime.3
index 8624a5f0..52c28bf3 100644
--- a/man/man3/tomo-Int.next_prime.3
+++ b/man/man3/tomo-Int.next_prime.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.next_prime 3 2025-04-21 "Tomo man-pages"
+.TH Int.next_prime 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.next_prime \- get the next prime
.SH LIBRARY
diff --git a/man/man3/tomo-Int.octal.3 b/man/man3/tomo-Int.octal.3
index 1ca994b4..e27b4015 100644
--- a/man/man3/tomo-Int.octal.3
+++ b/man/man3/tomo-Int.octal.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.octal 3 2025-04-21 "Tomo man-pages"
+.TH Int.octal 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.octal \- convert to octal
.SH LIBRARY
diff --git a/man/man3/tomo-Int.onward.3 b/man/man3/tomo-Int.onward.3
index 6d115a7a..5a930dfd 100644
--- a/man/man3/tomo-Int.onward.3
+++ b/man/man3/tomo-Int.onward.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.onward 3 2025-04-21 "Tomo man-pages"
+.TH Int.onward 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.onward \- iterate from a number onward
.SH LIBRARY
diff --git a/man/man3/tomo-Int.parse.3 b/man/man3/tomo-Int.parse.3
index 9db25774..9daac941 100644
--- a/man/man3/tomo-Int.parse.3
+++ b/man/man3/tomo-Int.parse.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.parse 3 2025-04-21 "Tomo man-pages"
+.TH Int.parse 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.parse \- convert text to integer
.SH LIBRARY
diff --git a/man/man3/tomo-Int.prev_prime.3 b/man/man3/tomo-Int.prev_prime.3
index a26bd5d8..eb7d9a77 100644
--- a/man/man3/tomo-Int.prev_prime.3
+++ b/man/man3/tomo-Int.prev_prime.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.prev_prime 3 2025-04-21 "Tomo man-pages"
+.TH Int.prev_prime 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.prev_prime \- get the previous prime
.SH LIBRARY
diff --git a/man/man3/tomo-Int.sqrt.3 b/man/man3/tomo-Int.sqrt.3
index 948595e3..79910749 100644
--- a/man/man3/tomo-Int.sqrt.3
+++ b/man/man3/tomo-Int.sqrt.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.sqrt 3 2025-04-21 "Tomo man-pages"
+.TH Int.sqrt 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.sqrt \- square root
.SH LIBRARY
diff --git a/man/man3/tomo-Int.to.3 b/man/man3/tomo-Int.to.3
index 9bc209ec..e62253e0 100644
--- a/man/man3/tomo-Int.to.3
+++ b/man/man3/tomo-Int.to.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Int.to 3 2025-04-21 "Tomo man-pages"
+.TH Int.to 3 2025-04-27 "Tomo man-pages"
.SH NAME
Int.to \- iterate a range of integers
.SH LIBRARY
diff --git a/man/man3/tomo-List.binary_search.3 b/man/man3/tomo-List.binary_search.3
index 7c3d39bb..24ae6549 100644
--- a/man/man3/tomo-List.binary_search.3
+++ b/man/man3/tomo-List.binary_search.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.binary_search 3 2025-04-21 "Tomo man-pages"
+.TH List.binary_search 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.binary_search \- binary search
.SH LIBRARY
diff --git a/man/man3/tomo-List.by.3 b/man/man3/tomo-List.by.3
index d4a125fe..2f01ae9d 100644
--- a/man/man3/tomo-List.by.3
+++ b/man/man3/tomo-List.by.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.by 3 2025-04-21 "Tomo man-pages"
+.TH List.by 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.by \- slice by a step value
.SH LIBRARY
diff --git a/man/man3/tomo-List.clear.3 b/man/man3/tomo-List.clear.3
index b1aecfc8..d97cb9e9 100644
--- a/man/man3/tomo-List.clear.3
+++ b/man/man3/tomo-List.clear.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.clear 3 2025-04-21 "Tomo man-pages"
+.TH List.clear 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.clear \- clear a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.counts.3 b/man/man3/tomo-List.counts.3
index 657fc6f5..04c189a7 100644
--- a/man/man3/tomo-List.counts.3
+++ b/man/man3/tomo-List.counts.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.counts 3 2025-04-21 "Tomo man-pages"
+.TH List.counts 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.counts \- count occurrences
.SH LIBRARY
diff --git a/man/man3/tomo-List.find.3 b/man/man3/tomo-List.find.3
index ecb77158..7427be7a 100644
--- a/man/man3/tomo-List.find.3
+++ b/man/man3/tomo-List.find.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.find 3 2025-04-21 "Tomo man-pages"
+.TH List.find 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.find \- find an element's index
.SH LIBRARY
diff --git a/man/man3/tomo-List.from.3 b/man/man3/tomo-List.from.3
index ecf0002f..36929015 100644
--- a/man/man3/tomo-List.from.3
+++ b/man/man3/tomo-List.from.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.from 3 2025-04-21 "Tomo man-pages"
+.TH List.from 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.from \- slice an array from a start index
.SH LIBRARY
diff --git a/man/man3/tomo-List.has.3 b/man/man3/tomo-List.has.3
index e4181048..1e5934b6 100644
--- a/man/man3/tomo-List.has.3
+++ b/man/man3/tomo-List.has.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.has 3 2025-04-21 "Tomo man-pages"
+.TH List.has 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.has \- check for member
.SH LIBRARY
diff --git a/man/man3/tomo-List.heap_pop.3 b/man/man3/tomo-List.heap_pop.3
index ae171295..ff5650b0 100644
--- a/man/man3/tomo-List.heap_pop.3
+++ b/man/man3/tomo-List.heap_pop.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.heap_pop 3 2025-04-21 "Tomo man-pages"
+.TH List.heap_pop 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.heap_pop \- heap pop
.SH LIBRARY
diff --git a/man/man3/tomo-List.heap_push.3 b/man/man3/tomo-List.heap_push.3
index 208c45d9..ca748f21 100644
--- a/man/man3/tomo-List.heap_push.3
+++ b/man/man3/tomo-List.heap_push.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.heap_push 3 2025-04-21 "Tomo man-pages"
+.TH List.heap_push 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.heap_push \- heap push
.SH LIBRARY
diff --git a/man/man3/tomo-List.heapify.3 b/man/man3/tomo-List.heapify.3
index 1a92bac4..78152cd6 100644
--- a/man/man3/tomo-List.heapify.3
+++ b/man/man3/tomo-List.heapify.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.heapify 3 2025-04-21 "Tomo man-pages"
+.TH List.heapify 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.heapify \- convert a list into a heap
.SH LIBRARY
diff --git a/man/man3/tomo-List.insert.3 b/man/man3/tomo-List.insert.3
index 3cf7c848..cd7bc6ae 100644
--- a/man/man3/tomo-List.insert.3
+++ b/man/man3/tomo-List.insert.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.insert 3 2025-04-21 "Tomo man-pages"
+.TH List.insert 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.insert \- add an item to a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.insert_all.3 b/man/man3/tomo-List.insert_all.3
index d6fa8dc4..afae20da 100644
--- a/man/man3/tomo-List.insert_all.3
+++ b/man/man3/tomo-List.insert_all.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.insert_all 3 2025-04-21 "Tomo man-pages"
+.TH List.insert_all 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.insert_all \- add multiple items to a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.pop.3 b/man/man3/tomo-List.pop.3
index 7d90d462..47d1039e 100644
--- a/man/man3/tomo-List.pop.3
+++ b/man/man3/tomo-List.pop.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.pop 3 2025-04-21 "Tomo man-pages"
+.TH List.pop 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.pop \- pop an item from a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.random.3 b/man/man3/tomo-List.random.3
index 65e22cde..97f49c09 100644
--- a/man/man3/tomo-List.random.3
+++ b/man/man3/tomo-List.random.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.random 3 2025-04-21 "Tomo man-pages"
+.TH List.random 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.random \- pick a random element
.SH LIBRARY
diff --git a/man/man3/tomo-List.remove_at.3 b/man/man3/tomo-List.remove_at.3
index 6e238814..9dcd0058 100644
--- a/man/man3/tomo-List.remove_at.3
+++ b/man/man3/tomo-List.remove_at.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.remove_at 3 2025-04-21 "Tomo man-pages"
+.TH List.remove_at 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.remove_at \- remove an item by index
.SH LIBRARY
diff --git a/man/man3/tomo-List.remove_item.3 b/man/man3/tomo-List.remove_item.3
index 6e1a5212..7cecf46e 100644
--- a/man/man3/tomo-List.remove_item.3
+++ b/man/man3/tomo-List.remove_item.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.remove_item 3 2025-04-21 "Tomo man-pages"
+.TH List.remove_item 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.remove_item \- remove an item by value
.SH LIBRARY
diff --git a/man/man3/tomo-List.reversed.3 b/man/man3/tomo-List.reversed.3
index 407bceba..fd96e918 100644
--- a/man/man3/tomo-List.reversed.3
+++ b/man/man3/tomo-List.reversed.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.reversed 3 2025-04-21 "Tomo man-pages"
+.TH List.reversed 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.reversed \- get a reversed list
.SH LIBRARY
diff --git a/man/man3/tomo-List.sample.3 b/man/man3/tomo-List.sample.3
index a4989b3e..53db479b 100644
--- a/man/man3/tomo-List.sample.3
+++ b/man/man3/tomo-List.sample.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.sample 3 2025-04-21 "Tomo man-pages"
+.TH List.sample 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.sample \- weighted random choices
.SH LIBRARY
diff --git a/man/man3/tomo-List.shuffle.3 b/man/man3/tomo-List.shuffle.3
index 56f7ba88..0aead852 100644
--- a/man/man3/tomo-List.shuffle.3
+++ b/man/man3/tomo-List.shuffle.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.shuffle 3 2025-04-21 "Tomo man-pages"
+.TH List.shuffle 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.shuffle \- shuffle a list in place
.SH LIBRARY
diff --git a/man/man3/tomo-List.shuffled.3 b/man/man3/tomo-List.shuffled.3
index 53a28a8f..154fe61c 100644
--- a/man/man3/tomo-List.shuffled.3
+++ b/man/man3/tomo-List.shuffled.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.shuffled 3 2025-04-21 "Tomo man-pages"
+.TH List.shuffled 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.shuffled \- return a shuffled list
.SH LIBRARY
diff --git a/man/man3/tomo-List.slice.3 b/man/man3/tomo-List.slice.3
index c9a2d2ac..ebc38f7b 100644
--- a/man/man3/tomo-List.slice.3
+++ b/man/man3/tomo-List.slice.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.slice 3 2025-04-21 "Tomo man-pages"
+.TH List.slice 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.slice \- get a slice of a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.sort.3 b/man/man3/tomo-List.sort.3
index fa35952b..b51155c2 100644
--- a/man/man3/tomo-List.sort.3
+++ b/man/man3/tomo-List.sort.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.sort 3 2025-04-21 "Tomo man-pages"
+.TH List.sort 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.sort \- sort a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.sorted.3 b/man/man3/tomo-List.sorted.3
index 1efe23d3..8f34d568 100644
--- a/man/man3/tomo-List.sorted.3
+++ b/man/man3/tomo-List.sorted.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.sorted 3 2025-04-21 "Tomo man-pages"
+.TH List.sorted 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.sorted \- sorted copy of a list
.SH LIBRARY
diff --git a/man/man3/tomo-List.to.3 b/man/man3/tomo-List.to.3
index f2ea346d..89580971 100644
--- a/man/man3/tomo-List.to.3
+++ b/man/man3/tomo-List.to.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.to 3 2025-04-21 "Tomo man-pages"
+.TH List.to 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.to \- slice a list to an end index
.SH LIBRARY
diff --git a/man/man3/tomo-List.unique.3 b/man/man3/tomo-List.unique.3
index f842fdc1..f5053a42 100644
--- a/man/man3/tomo-List.unique.3
+++ b/man/man3/tomo-List.unique.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.unique 3 2025-04-21 "Tomo man-pages"
+.TH List.unique 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.unique \- convert a list to a set
.SH LIBRARY
diff --git a/man/man3/tomo-List.where.3 b/man/man3/tomo-List.where.3
index 1bb9343b..118bfdec 100644
--- a/man/man3/tomo-List.where.3
+++ b/man/man3/tomo-List.where.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH List.where 3 2025-04-21 "Tomo man-pages"
+.TH List.where 3 2025-04-27 "Tomo man-pages"
.SH NAME
List.where \- find an index where a predicate matches
.SH LIBRARY
diff --git a/man/man3/tomo-Num.1_PI.3 b/man/man3/tomo-Num.1_PI.3
index afad67c1..bcb192e5 100644
--- a/man/man3/tomo-Num.1_PI.3
+++ b/man/man3/tomo-Num.1_PI.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.1_PI 3 2025-04-21 "Tomo man-pages"
+.TH Num.1_PI 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.1_PI \- 1/pi
.SH LIBRARY
diff --git a/man/man3/tomo-Num.2_PI.3 b/man/man3/tomo-Num.2_PI.3
index 6bf505bf..b10d7952 100644
--- a/man/man3/tomo-Num.2_PI.3
+++ b/man/man3/tomo-Num.2_PI.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.2_PI 3 2025-04-21 "Tomo man-pages"
+.TH Num.2_PI 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.2_PI \- 2*pi
.SH LIBRARY
diff --git a/man/man3/tomo-Num.2_SQRTPI.3 b/man/man3/tomo-Num.2_SQRTPI.3
index 1476403f..efc897ea 100644
--- a/man/man3/tomo-Num.2_SQRTPI.3
+++ b/man/man3/tomo-Num.2_SQRTPI.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.2_SQRTPI 3 2025-04-21 "Tomo man-pages"
+.TH Num.2_SQRTPI 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.2_SQRTPI \- 2*sqrt(pi)
.SH LIBRARY
diff --git a/man/man3/tomo-Num.E.3 b/man/man3/tomo-Num.E.3
index 08e76bba..a1fe8f8d 100644
--- a/man/man3/tomo-Num.E.3
+++ b/man/man3/tomo-Num.E.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.E 3 2025-04-21 "Tomo man-pages"
+.TH Num.E 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.E \- Euler's constant
.SH LIBRARY
diff --git a/man/man3/tomo-Num.INF.3 b/man/man3/tomo-Num.INF.3
index caac65f3..d2ad7f18 100644
--- a/man/man3/tomo-Num.INF.3
+++ b/man/man3/tomo-Num.INF.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.INF 3 2025-04-21 "Tomo man-pages"
+.TH Num.INF 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.INF \- infinity
.SH LIBRARY
diff --git a/man/man3/tomo-Num.LN10.3 b/man/man3/tomo-Num.LN10.3
index d2514530..7d5085ae 100644
--- a/man/man3/tomo-Num.LN10.3
+++ b/man/man3/tomo-Num.LN10.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.LN10 3 2025-04-21 "Tomo man-pages"
+.TH Num.LN10 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.LN10 \- log(10)
.SH LIBRARY
diff --git a/man/man3/tomo-Num.LN2.3 b/man/man3/tomo-Num.LN2.3
index 73fb86fa..9610ccbd 100644
--- a/man/man3/tomo-Num.LN2.3
+++ b/man/man3/tomo-Num.LN2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.LN2 3 2025-04-21 "Tomo man-pages"
+.TH Num.LN2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.LN2 \- log(2)
.SH LIBRARY
diff --git a/man/man3/tomo-Num.LOG2E.3 b/man/man3/tomo-Num.LOG2E.3
index 987277f7..3069fcd6 100644
--- a/man/man3/tomo-Num.LOG2E.3
+++ b/man/man3/tomo-Num.LOG2E.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.LOG2E 3 2025-04-21 "Tomo man-pages"
+.TH Num.LOG2E 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.LOG2E \- log_2(e)
.SH LIBRARY
diff --git a/man/man3/tomo-Num.PI.3 b/man/man3/tomo-Num.PI.3
index c5bd8539..8403957b 100644
--- a/man/man3/tomo-Num.PI.3
+++ b/man/man3/tomo-Num.PI.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.PI 3 2025-04-21 "Tomo man-pages"
+.TH Num.PI 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.PI \- pi
.SH LIBRARY
diff --git a/man/man3/tomo-Num.PI_2.3 b/man/man3/tomo-Num.PI_2.3
index 8da9ccfe..2598a595 100644
--- a/man/man3/tomo-Num.PI_2.3
+++ b/man/man3/tomo-Num.PI_2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.PI_2 3 2025-04-21 "Tomo man-pages"
+.TH Num.PI_2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.PI_2 \- pi/2
.SH LIBRARY
diff --git a/man/man3/tomo-Num.PI_4.3 b/man/man3/tomo-Num.PI_4.3
index 168e8ccb..a41462ed 100644
--- a/man/man3/tomo-Num.PI_4.3
+++ b/man/man3/tomo-Num.PI_4.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.PI_4 3 2025-04-21 "Tomo man-pages"
+.TH Num.PI_4 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.PI_4 \- pi/4
.SH LIBRARY
diff --git a/man/man3/tomo-Num.SQRT1_2.3 b/man/man3/tomo-Num.SQRT1_2.3
index e023b27c..b4fbda6f 100644
--- a/man/man3/tomo-Num.SQRT1_2.3
+++ b/man/man3/tomo-Num.SQRT1_2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.SQRT1_2 3 2025-04-21 "Tomo man-pages"
+.TH Num.SQRT1_2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.SQRT1_2 \- sqrt(1/2)
.SH LIBRARY
diff --git a/man/man3/tomo-Num.SQRT2.3 b/man/man3/tomo-Num.SQRT2.3
index e4e34ce9..580e2d59 100644
--- a/man/man3/tomo-Num.SQRT2.3
+++ b/man/man3/tomo-Num.SQRT2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.SQRT2 3 2025-04-21 "Tomo man-pages"
+.TH Num.SQRT2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.SQRT2 \- sqrt(2)
.SH LIBRARY
diff --git a/man/man3/tomo-Num.TAU.3 b/man/man3/tomo-Num.TAU.3
index d13c5207..5990a861 100644
--- a/man/man3/tomo-Num.TAU.3
+++ b/man/man3/tomo-Num.TAU.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.TAU 3 2025-04-21 "Tomo man-pages"
+.TH Num.TAU 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.TAU \- 2*pi
.SH LIBRARY
diff --git a/man/man3/tomo-Num.abs.3 b/man/man3/tomo-Num.abs.3
index 6fc79b70..9fb30788 100644
--- a/man/man3/tomo-Num.abs.3
+++ b/man/man3/tomo-Num.abs.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.abs 3 2025-04-21 "Tomo man-pages"
+.TH Num.abs 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.abs \- absolute value
.SH LIBRARY
diff --git a/man/man3/tomo-Num.acos.3 b/man/man3/tomo-Num.acos.3
index 25bd26be..4e454058 100644
--- a/man/man3/tomo-Num.acos.3
+++ b/man/man3/tomo-Num.acos.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.acos 3 2025-04-21 "Tomo man-pages"
+.TH Num.acos 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.acos \- arc cosine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.acosh.3 b/man/man3/tomo-Num.acosh.3
index c9b50aab..826b92c5 100644
--- a/man/man3/tomo-Num.acosh.3
+++ b/man/man3/tomo-Num.acosh.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.acosh 3 2025-04-21 "Tomo man-pages"
+.TH Num.acosh 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.acosh \- arc hyperbolic cosine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.asin.3 b/man/man3/tomo-Num.asin.3
index 77b732f4..4c2f619b 100644
--- a/man/man3/tomo-Num.asin.3
+++ b/man/man3/tomo-Num.asin.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.asin 3 2025-04-21 "Tomo man-pages"
+.TH Num.asin 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.asin \- arc sine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.asinh.3 b/man/man3/tomo-Num.asinh.3
index c2b50fdd..13b81c98 100644
--- a/man/man3/tomo-Num.asinh.3
+++ b/man/man3/tomo-Num.asinh.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.asinh 3 2025-04-21 "Tomo man-pages"
+.TH Num.asinh 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.asinh \- arc hyperbolic sine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.atan.3 b/man/man3/tomo-Num.atan.3
index 7a4d7e33..d382d5fd 100644
--- a/man/man3/tomo-Num.atan.3
+++ b/man/man3/tomo-Num.atan.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.atan 3 2025-04-21 "Tomo man-pages"
+.TH Num.atan 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.atan \- arc tangent
.SH LIBRARY
diff --git a/man/man3/tomo-Num.atan2.3 b/man/man3/tomo-Num.atan2.3
index c45d28cb..020139b1 100644
--- a/man/man3/tomo-Num.atan2.3
+++ b/man/man3/tomo-Num.atan2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.atan2 3 2025-04-21 "Tomo man-pages"
+.TH Num.atan2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.atan2 \- arc tangent from 2 variables
.SH LIBRARY
diff --git a/man/man3/tomo-Num.atanh.3 b/man/man3/tomo-Num.atanh.3
index 7e5405ce..e0d2cb35 100644
--- a/man/man3/tomo-Num.atanh.3
+++ b/man/man3/tomo-Num.atanh.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.atanh 3 2025-04-21 "Tomo man-pages"
+.TH Num.atanh 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.atanh \- arc hyperbolic tangent.
.SH LIBRARY
diff --git a/man/man3/tomo-Num.cbrt.3 b/man/man3/tomo-Num.cbrt.3
index b71d1d47..d645bc68 100644
--- a/man/man3/tomo-Num.cbrt.3
+++ b/man/man3/tomo-Num.cbrt.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.cbrt 3 2025-04-21 "Tomo man-pages"
+.TH Num.cbrt 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.cbrt \- cube root
.SH LIBRARY
diff --git a/man/man3/tomo-Num.ceil.3 b/man/man3/tomo-Num.ceil.3
index 4a949da0..ad13d193 100644
--- a/man/man3/tomo-Num.ceil.3
+++ b/man/man3/tomo-Num.ceil.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.ceil 3 2025-04-21 "Tomo man-pages"
+.TH Num.ceil 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.ceil \- ceiling function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.clamped.3 b/man/man3/tomo-Num.clamped.3
index 8d7184b0..ceae7de0 100644
--- a/man/man3/tomo-Num.clamped.3
+++ b/man/man3/tomo-Num.clamped.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.clamped 3 2025-04-21 "Tomo man-pages"
+.TH Num.clamped 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.clamped \- clamp a number
.SH LIBRARY
diff --git a/man/man3/tomo-Num.copysign.3 b/man/man3/tomo-Num.copysign.3
index da25d705..b9829367 100644
--- a/man/man3/tomo-Num.copysign.3
+++ b/man/man3/tomo-Num.copysign.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.copysign 3 2025-04-21 "Tomo man-pages"
+.TH Num.copysign 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.copysign \- copy a number's sign
.SH LIBRARY
diff --git a/man/man3/tomo-Num.cos.3 b/man/man3/tomo-Num.cos.3
index 1a1e92cc..edb0e48b 100644
--- a/man/man3/tomo-Num.cos.3
+++ b/man/man3/tomo-Num.cos.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.cos 3 2025-04-21 "Tomo man-pages"
+.TH Num.cos 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.cos \- cosine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.cosh.3 b/man/man3/tomo-Num.cosh.3
index 5648cbf2..32e63287 100644
--- a/man/man3/tomo-Num.cosh.3
+++ b/man/man3/tomo-Num.cosh.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.cosh 3 2025-04-21 "Tomo man-pages"
+.TH Num.cosh 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.cosh \- hyperbolic cosine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.erf.3 b/man/man3/tomo-Num.erf.3
index 80c4d626..d4756e0a 100644
--- a/man/man3/tomo-Num.erf.3
+++ b/man/man3/tomo-Num.erf.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.erf 3 2025-04-21 "Tomo man-pages"
+.TH Num.erf 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.erf \- error function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.erfc.3 b/man/man3/tomo-Num.erfc.3
index 5da1e372..f904dcb2 100644
--- a/man/man3/tomo-Num.erfc.3
+++ b/man/man3/tomo-Num.erfc.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.erfc 3 2025-04-21 "Tomo man-pages"
+.TH Num.erfc 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.erfc \- complimentary error function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.exp.3 b/man/man3/tomo-Num.exp.3
index c1d759ae..1d2c78a9 100644
--- a/man/man3/tomo-Num.exp.3
+++ b/man/man3/tomo-Num.exp.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.exp 3 2025-04-21 "Tomo man-pages"
+.TH Num.exp 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.exp \- base-e exponentiation
.SH LIBRARY
diff --git a/man/man3/tomo-Num.exp2.3 b/man/man3/tomo-Num.exp2.3
index e078d727..e3b1b708 100644
--- a/man/man3/tomo-Num.exp2.3
+++ b/man/man3/tomo-Num.exp2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.exp2 3 2025-04-21 "Tomo man-pages"
+.TH Num.exp2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.exp2 \- base-2 exponentiation
.SH LIBRARY
diff --git a/man/man3/tomo-Num.expm1.3 b/man/man3/tomo-Num.expm1.3
index c1172f0e..440647a3 100644
--- a/man/man3/tomo-Num.expm1.3
+++ b/man/man3/tomo-Num.expm1.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.expm1 3 2025-04-21 "Tomo man-pages"
+.TH Num.expm1 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.expm1 \- base-e exponential minus 1
.SH LIBRARY
diff --git a/man/man3/tomo-Num.fdim.3 b/man/man3/tomo-Num.fdim.3
index f5dc3955..52deaf80 100644
--- a/man/man3/tomo-Num.fdim.3
+++ b/man/man3/tomo-Num.fdim.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.fdim 3 2025-04-21 "Tomo man-pages"
+.TH Num.fdim 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.fdim \- positive difference
.SH LIBRARY
diff --git a/man/man3/tomo-Num.floor.3 b/man/man3/tomo-Num.floor.3
index bfa34525..32ec2792 100644
--- a/man/man3/tomo-Num.floor.3
+++ b/man/man3/tomo-Num.floor.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.floor 3 2025-04-21 "Tomo man-pages"
+.TH Num.floor 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.floor \- floor function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.format.3 b/man/man3/tomo-Num.format.3
deleted file mode 100644
index 26474775..00000000
--- a/man/man3/tomo-Num.format.3
+++ /dev/null
@@ -1,35 +0,0 @@
-'\" t
-.\" Copyright (c) 2025 Bruce Hill
-.\" All rights reserved.
-.\"
-.TH Num.format 3 2025-04-21 "Tomo man-pages"
-.SH NAME
-Num.format \- convert a number to text
-.SH LIBRARY
-Tomo Standard Library
-.SH SYNOPSIS
-.nf
-.BI Num.format\ :\ func(n:\ Num,\ precision:\ Int\ =\ 0\ ->\ Text)
-.fi
-.SH DESCRIPTION
-Formats a number as a text with a specified precision.
-
-
-.SH ARGUMENTS
-
-.TS
-allbox;
-lb lb lbx lb
-l l l l.
-Name Type Description Default
-n Num The number to be formatted. -
-precision Int The number of decimal places. Default is `0`. 0
-.TE
-.SH RETURN
-A text representation of the number with the specified precision.
-
-.SH EXAMPLES
-.EX
->> (3.14159).format(precision=2)
-= "3.14"
-.EE
diff --git a/man/man3/tomo-Num.hypot.3 b/man/man3/tomo-Num.hypot.3
index f69b31f7..f45b695d 100644
--- a/man/man3/tomo-Num.hypot.3
+++ b/man/man3/tomo-Num.hypot.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.hypot 3 2025-04-21 "Tomo man-pages"
+.TH Num.hypot 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.hypot \- Euclidean distance function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.is_between.3 b/man/man3/tomo-Num.is_between.3
index 120e8e4a..c548fa5a 100644
--- a/man/man3/tomo-Num.is_between.3
+++ b/man/man3/tomo-Num.is_between.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.is_between 3 2025-04-21 "Tomo man-pages"
+.TH Num.is_between 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.is_between \- check if a number is in a range
.SH LIBRARY
diff --git a/man/man3/tomo-Num.isfinite.3 b/man/man3/tomo-Num.isfinite.3
index 8aa2d523..1b3692e3 100644
--- a/man/man3/tomo-Num.isfinite.3
+++ b/man/man3/tomo-Num.isfinite.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.isfinite 3 2025-04-21 "Tomo man-pages"
+.TH Num.isfinite 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.isfinite \- check for finite number
.SH LIBRARY
diff --git a/man/man3/tomo-Num.isinf.3 b/man/man3/tomo-Num.isinf.3
index e3bf680b..aba7fd15 100644
--- a/man/man3/tomo-Num.isinf.3
+++ b/man/man3/tomo-Num.isinf.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.isinf 3 2025-04-21 "Tomo man-pages"
+.TH Num.isinf 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.isinf \- check for infinite number
.SH LIBRARY
diff --git a/man/man3/tomo-Num.j0.3 b/man/man3/tomo-Num.j0.3
index 79e2761c..ae55300a 100644
--- a/man/man3/tomo-Num.j0.3
+++ b/man/man3/tomo-Num.j0.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.j0 3 2025-04-21 "Tomo man-pages"
+.TH Num.j0 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.j0 \- Bessel function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.j1.3 b/man/man3/tomo-Num.j1.3
index bf3258df..1f2af252 100644
--- a/man/man3/tomo-Num.j1.3
+++ b/man/man3/tomo-Num.j1.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.j1 3 2025-04-21 "Tomo man-pages"
+.TH Num.j1 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.j1 \- Bessel function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.log.3 b/man/man3/tomo-Num.log.3
index fe580ad4..8105fa23 100644
--- a/man/man3/tomo-Num.log.3
+++ b/man/man3/tomo-Num.log.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.log 3 2025-04-21 "Tomo man-pages"
+.TH Num.log 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.log \- natural logarithm
.SH LIBRARY
diff --git a/man/man3/tomo-Num.log10.3 b/man/man3/tomo-Num.log10.3
index be8d0ccf..a85c0f37 100644
--- a/man/man3/tomo-Num.log10.3
+++ b/man/man3/tomo-Num.log10.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.log10 3 2025-04-21 "Tomo man-pages"
+.TH Num.log10 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.log10 \- logarithm base-10
.SH LIBRARY
diff --git a/man/man3/tomo-Num.log1p.3 b/man/man3/tomo-Num.log1p.3
index 57ddfe13..b72e6602 100644
--- a/man/man3/tomo-Num.log1p.3
+++ b/man/man3/tomo-Num.log1p.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.log1p 3 2025-04-21 "Tomo man-pages"
+.TH Num.log1p 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.log1p \- logarithm of 1 plus x
.SH LIBRARY
diff --git a/man/man3/tomo-Num.log2.3 b/man/man3/tomo-Num.log2.3
index 69272e6d..44567956 100644
--- a/man/man3/tomo-Num.log2.3
+++ b/man/man3/tomo-Num.log2.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.log2 3 2025-04-21 "Tomo man-pages"
+.TH Num.log2 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.log2 \- logarithm base-2
.SH LIBRARY
diff --git a/man/man3/tomo-Num.logb.3 b/man/man3/tomo-Num.logb.3
index 13a08468..8340003b 100644
--- a/man/man3/tomo-Num.logb.3
+++ b/man/man3/tomo-Num.logb.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.logb 3 2025-04-21 "Tomo man-pages"
+.TH Num.logb 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.logb \- exponent of a floating point value
.SH LIBRARY
diff --git a/man/man3/tomo-Num.mix.3 b/man/man3/tomo-Num.mix.3
index 2e3140cd..7a235b53 100644
--- a/man/man3/tomo-Num.mix.3
+++ b/man/man3/tomo-Num.mix.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.mix 3 2025-04-21 "Tomo man-pages"
+.TH Num.mix 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.mix \- mix two numbers by an amount
.SH LIBRARY
diff --git a/man/man3/tomo-Num.near.3 b/man/man3/tomo-Num.near.3
index 44560cc5..afa5384b 100644
--- a/man/man3/tomo-Num.near.3
+++ b/man/man3/tomo-Num.near.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.near 3 2025-04-21 "Tomo man-pages"
+.TH Num.near 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.near \- check if two numbers are near each other
.SH LIBRARY
diff --git a/man/man3/tomo-Num.nextafter.3 b/man/man3/tomo-Num.nextafter.3
index 18462f55..28132746 100644
--- a/man/man3/tomo-Num.nextafter.3
+++ b/man/man3/tomo-Num.nextafter.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.nextafter 3 2025-04-21 "Tomo man-pages"
+.TH Num.nextafter 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.nextafter \- next floating point number
.SH LIBRARY
diff --git a/man/man3/tomo-Num.parse.3 b/man/man3/tomo-Num.parse.3
index 2cd33d38..150b854b 100644
--- a/man/man3/tomo-Num.parse.3
+++ b/man/man3/tomo-Num.parse.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.parse 3 2025-04-21 "Tomo man-pages"
+.TH Num.parse 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.parse \- convert text to number
.SH LIBRARY
diff --git a/man/man3/tomo-Num.percent.3 b/man/man3/tomo-Num.percent.3
index ee092b53..33b78657 100644
--- a/man/man3/tomo-Num.percent.3
+++ b/man/man3/tomo-Num.percent.3
@@ -2,14 +2,14 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.percent 3 2025-04-21 "Tomo man-pages"
+.TH Num.percent 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.percent \- format as a percentage
.SH LIBRARY
Tomo Standard Library
.SH SYNOPSIS
.nf
-.BI Num.percent\ :\ func(n:\ Num,\ precision:\ Int\ =\ 0\ ->\ Text)
+.BI Num.percent\ :\ func(n:\ Num,\ precision:\ Num\ =\ 0.01\ ->\ Text)
.fi
.SH DESCRIPTION
Convert a number into a percentage text with a percent sign.
@@ -23,7 +23,7 @@ lb lb lbx lb
l l l l.
Name Type Description Default
n Num The number to be converted to a percent. -
-precision Int The number of decimal places. Default is `0`. 0
+precision Num Round the percentage to this precision level. 0.01
.TE
.SH RETURN
A text representation of the number as a percentage with a percent sign.
@@ -34,4 +34,8 @@ A text representation of the number as a percentage with a percent sign.
= "50%"
>> (1./3.).percent(2)
= "33.33%"
+>> (1./3.).percent(2, precision=0.0001)
+= "33.3333%"
+>> (1./3.).percent(2, precision=10.)
+= "30%"
.EE
diff --git a/man/man3/tomo-Num.rint.3 b/man/man3/tomo-Num.rint.3
index 82a80e42..01f5fde7 100644
--- a/man/man3/tomo-Num.rint.3
+++ b/man/man3/tomo-Num.rint.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.rint 3 2025-04-21 "Tomo man-pages"
+.TH Num.rint 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.rint \- round to nearest integer
.SH LIBRARY
diff --git a/man/man3/tomo-Num.round.3 b/man/man3/tomo-Num.round.3
index 6a3ad92b..ed32b5a8 100644
--- a/man/man3/tomo-Num.round.3
+++ b/man/man3/tomo-Num.round.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.round 3 2025-04-21 "Tomo man-pages"
+.TH Num.round 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.round \- round to nearest integer
.SH LIBRARY
diff --git a/man/man3/tomo-Num.scientific.3 b/man/man3/tomo-Num.scientific.3
deleted file mode 100644
index f4b11224..00000000
--- a/man/man3/tomo-Num.scientific.3
+++ /dev/null
@@ -1,35 +0,0 @@
-'\" t
-.\" Copyright (c) 2025 Bruce Hill
-.\" All rights reserved.
-.\"
-.TH Num.scientific 3 2025-04-21 "Tomo man-pages"
-.SH NAME
-Num.scientific \- format in scientific notation
-.SH LIBRARY
-Tomo Standard Library
-.SH SYNOPSIS
-.nf
-.BI Num.scientific\ :\ func(n:\ Num,\ precision:\ Int\ =\ 0\ ->\ Text)
-.fi
-.SH DESCRIPTION
-Formats a number in scientific notation with a specified precision.
-
-
-.SH ARGUMENTS
-
-.TS
-allbox;
-lb lb lbx lb
-l l l l.
-Name Type Description Default
-n Num The number to be formatted. -
-precision Int The number of decimal places. Default is `0`. 0
-.TE
-.SH RETURN
-A text representation of the number in scientific notation with the specified precision.
-
-.SH EXAMPLES
-.EX
->> (12345.6789).scientific(precision=2)
-= "1.23e+04"
-.EE
diff --git a/man/man3/tomo-Num.significand.3 b/man/man3/tomo-Num.significand.3
index 6f6c8128..4babe243 100644
--- a/man/man3/tomo-Num.significand.3
+++ b/man/man3/tomo-Num.significand.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.significand 3 2025-04-21 "Tomo man-pages"
+.TH Num.significand 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.significand \- get mantissa
.SH LIBRARY
diff --git a/man/man3/tomo-Num.sin.3 b/man/man3/tomo-Num.sin.3
index a97e4eeb..e814e512 100644
--- a/man/man3/tomo-Num.sin.3
+++ b/man/man3/tomo-Num.sin.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.sin 3 2025-04-21 "Tomo man-pages"
+.TH Num.sin 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.sin \- sine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.sinh.3 b/man/man3/tomo-Num.sinh.3
index 2bc2221b..6e995c88 100644
--- a/man/man3/tomo-Num.sinh.3
+++ b/man/man3/tomo-Num.sinh.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.sinh 3 2025-04-21 "Tomo man-pages"
+.TH Num.sinh 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.sinh \- hyperbolic sine
.SH LIBRARY
diff --git a/man/man3/tomo-Num.sqrt.3 b/man/man3/tomo-Num.sqrt.3
index 3032837d..3b8a79a8 100644
--- a/man/man3/tomo-Num.sqrt.3
+++ b/man/man3/tomo-Num.sqrt.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.sqrt 3 2025-04-21 "Tomo man-pages"
+.TH Num.sqrt 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.sqrt \- square root
.SH LIBRARY
diff --git a/man/man3/tomo-Num.tan.3 b/man/man3/tomo-Num.tan.3
index 7c8940aa..0a3e7608 100644
--- a/man/man3/tomo-Num.tan.3
+++ b/man/man3/tomo-Num.tan.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.tan 3 2025-04-21 "Tomo man-pages"
+.TH Num.tan 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.tan \- tangent
.SH LIBRARY
diff --git a/man/man3/tomo-Num.tanh.3 b/man/man3/tomo-Num.tanh.3
index b3296873..f57f6d89 100644
--- a/man/man3/tomo-Num.tanh.3
+++ b/man/man3/tomo-Num.tanh.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.tanh 3 2025-04-21 "Tomo man-pages"
+.TH Num.tanh 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.tanh \- hyperbolic tangent
.SH LIBRARY
diff --git a/man/man3/tomo-Num.tgamma.3 b/man/man3/tomo-Num.tgamma.3
index 1295f1d1..7e264dff 100644
--- a/man/man3/tomo-Num.tgamma.3
+++ b/man/man3/tomo-Num.tgamma.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.tgamma 3 2025-04-21 "Tomo man-pages"
+.TH Num.tgamma 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.tgamma \- true gamma function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.trunc.3 b/man/man3/tomo-Num.trunc.3
index 4ca7d6c3..392e07dc 100644
--- a/man/man3/tomo-Num.trunc.3
+++ b/man/man3/tomo-Num.trunc.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.trunc 3 2025-04-21 "Tomo man-pages"
+.TH Num.trunc 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.trunc \- truncate a number
.SH LIBRARY
diff --git a/man/man3/tomo-Num.with_precision.3 b/man/man3/tomo-Num.with_precision.3
new file mode 100644
index 00000000..61b2795f
--- /dev/null
+++ b/man/man3/tomo-Num.with_precision.3
@@ -0,0 +1,39 @@
+'\" t
+.\" Copyright (c) 2025 Bruce Hill
+.\" All rights reserved.
+.\"
+.TH Num.with_precision 3 2025-04-27 "Tomo man-pages"
+.SH NAME
+Num.with_precision \- round to a given precision
+.SH LIBRARY
+Tomo Standard Library
+.SH SYNOPSIS
+.nf
+.BI Num.with_precision\ :\ func(n:\ Num,\ precision:\ Num\ ->\ Num)
+.fi
+.SH DESCRIPTION
+Round a number to the given precision level (specified as `10`, `.1`, `.001` etc).
+
+
+.SH ARGUMENTS
+
+.TS
+allbox;
+lb lb lbx lb
+l l l l.
+Name Type Description Default
+n Num The number to be rounded to a given precision. -
+precision Num The precision to which the number should be rounded. -
+.TE
+.SH RETURN
+The number, rounded to the given precision level.
+
+.SH EXAMPLES
+.EX
+>> (0.1234567).with_precision(0.01)
+= 0.12
+>> (123456.).with_precision(100)
+= 123500
+>> (1234567.).with_precision(5)
+= 1234565
+.EE
diff --git a/man/man3/tomo-Num.y0.3 b/man/man3/tomo-Num.y0.3
index 994fc965..7c49f82b 100644
--- a/man/man3/tomo-Num.y0.3
+++ b/man/man3/tomo-Num.y0.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.y0 3 2025-04-21 "Tomo man-pages"
+.TH Num.y0 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.y0 \- Bessel function
.SH LIBRARY
diff --git a/man/man3/tomo-Num.y1.3 b/man/man3/tomo-Num.y1.3
index 74c387f1..918726a6 100644
--- a/man/man3/tomo-Num.y1.3
+++ b/man/man3/tomo-Num.y1.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Num.y1 3 2025-04-21 "Tomo man-pages"
+.TH Num.y1 3 2025-04-27 "Tomo man-pages"
.SH NAME
Num.y1 \- Bessel function
.SH LIBRARY
diff --git a/man/man3/tomo-Path.accessed.3 b/man/man3/tomo-Path.accessed.3
index b434a8e5..b531671d 100644
--- a/man/man3/tomo-Path.accessed.3
+++ b/man/man3/tomo-Path.accessed.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.accessed 3 2025-04-21 "Tomo man-pages"
+.TH Path.accessed 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.accessed \- access time
.SH LIBRARY
diff --git a/man/man3/tomo-Path.append.3 b/man/man3/tomo-Path.append.3
index 79450516..e00e3f29 100644
--- a/man/man3/tomo-Path.append.3
+++ b/man/man3/tomo-Path.append.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.append 3 2025-04-21 "Tomo man-pages"
+.TH Path.append 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.append \- append to a file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.append_bytes.3 b/man/man3/tomo-Path.append_bytes.3
index 6284de02..6da5aa10 100644
--- a/man/man3/tomo-Path.append_bytes.3
+++ b/man/man3/tomo-Path.append_bytes.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.append_bytes 3 2025-04-21 "Tomo man-pages"
+.TH Path.append_bytes 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.append_bytes \- append bytes to a file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.base_name.3 b/man/man3/tomo-Path.base_name.3
index 61ecde20..0b50e8f3 100644
--- a/man/man3/tomo-Path.base_name.3
+++ b/man/man3/tomo-Path.base_name.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.base_name 3 2025-04-21 "Tomo man-pages"
+.TH Path.base_name 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.base_name \- base name of a file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.by_line.3 b/man/man3/tomo-Path.by_line.3
index c017039c..d83e5056 100644
--- a/man/man3/tomo-Path.by_line.3
+++ b/man/man3/tomo-Path.by_line.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.by_line 3 2025-04-21 "Tomo man-pages"
+.TH Path.by_line 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.by_line \- iterate by line
.SH LIBRARY
diff --git a/man/man3/tomo-Path.can_execute.3 b/man/man3/tomo-Path.can_execute.3
index d4881908..ed33db56 100644
--- a/man/man3/tomo-Path.can_execute.3
+++ b/man/man3/tomo-Path.can_execute.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.can_execute 3 2025-04-21 "Tomo man-pages"
+.TH Path.can_execute 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.can_execute \- check execute permissions
.SH LIBRARY
diff --git a/man/man3/tomo-Path.can_read.3 b/man/man3/tomo-Path.can_read.3
index f2291dda..4b5058ce 100644
--- a/man/man3/tomo-Path.can_read.3
+++ b/man/man3/tomo-Path.can_read.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.can_read 3 2025-04-21 "Tomo man-pages"
+.TH Path.can_read 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.can_read \- check read permissions
.SH LIBRARY
diff --git a/man/man3/tomo-Path.can_write.3 b/man/man3/tomo-Path.can_write.3
index 6077e490..0bd67732 100644
--- a/man/man3/tomo-Path.can_write.3
+++ b/man/man3/tomo-Path.can_write.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.can_write 3 2025-04-21 "Tomo man-pages"
+.TH Path.can_write 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.can_write \- check write permissions
.SH LIBRARY
diff --git a/man/man3/tomo-Path.changed.3 b/man/man3/tomo-Path.changed.3
index 12d7a31e..db73a090 100644
--- a/man/man3/tomo-Path.changed.3
+++ b/man/man3/tomo-Path.changed.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.changed 3 2025-04-21 "Tomo man-pages"
+.TH Path.changed 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.changed \- get the last changed time
.SH LIBRARY
diff --git a/man/man3/tomo-Path.child.3 b/man/man3/tomo-Path.child.3
index 2e0f5c93..7017dd8a 100644
--- a/man/man3/tomo-Path.child.3
+++ b/man/man3/tomo-Path.child.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.child 3 2025-04-21 "Tomo man-pages"
+.TH Path.child 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.child \- append a child to a path
.SH LIBRARY
diff --git a/man/man3/tomo-Path.children.3 b/man/man3/tomo-Path.children.3
index 55de97a9..006b4712 100644
--- a/man/man3/tomo-Path.children.3
+++ b/man/man3/tomo-Path.children.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.children 3 2025-04-21 "Tomo man-pages"
+.TH Path.children 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.children \- get children of a directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.create_directory.3 b/man/man3/tomo-Path.create_directory.3
index 322b58f2..caa3b13c 100644
--- a/man/man3/tomo-Path.create_directory.3
+++ b/man/man3/tomo-Path.create_directory.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.create_directory 3 2025-04-21 "Tomo man-pages"
+.TH Path.create_directory 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.create_directory \- make a directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.current_dir.3 b/man/man3/tomo-Path.current_dir.3
index 06ded3e9..0f927211 100644
--- a/man/man3/tomo-Path.current_dir.3
+++ b/man/man3/tomo-Path.current_dir.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.current_dir 3 2025-04-21 "Tomo man-pages"
+.TH Path.current_dir 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.current_dir \- get current directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.exists.3 b/man/man3/tomo-Path.exists.3
index 371c695f..6746ff37 100644
--- a/man/man3/tomo-Path.exists.3
+++ b/man/man3/tomo-Path.exists.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.exists 3 2025-04-21 "Tomo man-pages"
+.TH Path.exists 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.exists \- check if a path exists
.SH LIBRARY
diff --git a/man/man3/tomo-Path.expand_home.3 b/man/man3/tomo-Path.expand_home.3
index 00d5bac6..4b947527 100644
--- a/man/man3/tomo-Path.expand_home.3
+++ b/man/man3/tomo-Path.expand_home.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.expand_home 3 2025-04-21 "Tomo man-pages"
+.TH Path.expand_home 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.expand_home \- expand ~ to $HOME
.SH LIBRARY
diff --git a/man/man3/tomo-Path.extension.3 b/man/man3/tomo-Path.extension.3
index e27c7639..23d8ff6b 100644
--- a/man/man3/tomo-Path.extension.3
+++ b/man/man3/tomo-Path.extension.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.extension 3 2025-04-21 "Tomo man-pages"
+.TH Path.extension 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.extension \- get file extension
.SH LIBRARY
diff --git a/man/man3/tomo-Path.files.3 b/man/man3/tomo-Path.files.3
index 7c59ce67..01123332 100644
--- a/man/man3/tomo-Path.files.3
+++ b/man/man3/tomo-Path.files.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.files 3 2025-04-21 "Tomo man-pages"
+.TH Path.files 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.files \- list files in a directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.from_components.3 b/man/man3/tomo-Path.from_components.3
index 2f392779..c239da60 100644
--- a/man/man3/tomo-Path.from_components.3
+++ b/man/man3/tomo-Path.from_components.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.from_components 3 2025-04-21 "Tomo man-pages"
+.TH Path.from_components 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.from_components \- build a path from components
.SH LIBRARY
diff --git a/man/man3/tomo-Path.glob.3 b/man/man3/tomo-Path.glob.3
index be4a6336..47e28862 100644
--- a/man/man3/tomo-Path.glob.3
+++ b/man/man3/tomo-Path.glob.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.glob 3 2025-04-21 "Tomo man-pages"
+.TH Path.glob 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.glob \- perform file globbing
.SH LIBRARY
diff --git a/man/man3/tomo-Path.group.3 b/man/man3/tomo-Path.group.3
index 4f3d8c1c..887165a9 100644
--- a/man/man3/tomo-Path.group.3
+++ b/man/man3/tomo-Path.group.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.group 3 2025-04-21 "Tomo man-pages"
+.TH Path.group 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.group \- get the owning group
.SH LIBRARY
diff --git a/man/man3/tomo-Path.is_directory.3 b/man/man3/tomo-Path.is_directory.3
index 92479c48..16cf907d 100644
--- a/man/man3/tomo-Path.is_directory.3
+++ b/man/man3/tomo-Path.is_directory.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.is_directory 3 2025-04-21 "Tomo man-pages"
+.TH Path.is_directory 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.is_directory \- check if a path is a directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.is_file.3 b/man/man3/tomo-Path.is_file.3
index 505f86a6..d8fd26ac 100644
--- a/man/man3/tomo-Path.is_file.3
+++ b/man/man3/tomo-Path.is_file.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.is_file 3 2025-04-21 "Tomo man-pages"
+.TH Path.is_file 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.is_file \- check if a path is a file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.is_socket.3 b/man/man3/tomo-Path.is_socket.3
index f54df228..b9c7d9dc 100644
--- a/man/man3/tomo-Path.is_socket.3
+++ b/man/man3/tomo-Path.is_socket.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.is_socket 3 2025-04-21 "Tomo man-pages"
+.TH Path.is_socket 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.is_socket \- check if a path is a socket
.SH LIBRARY
diff --git a/man/man3/tomo-Path.is_symlink.3 b/man/man3/tomo-Path.is_symlink.3
index 818a53ea..f4808038 100644
--- a/man/man3/tomo-Path.is_symlink.3
+++ b/man/man3/tomo-Path.is_symlink.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.is_symlink 3 2025-04-21 "Tomo man-pages"
+.TH Path.is_symlink 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.is_symlink \- check if a path is a symbolic link
.SH LIBRARY
diff --git a/man/man3/tomo-Path.modified.3 b/man/man3/tomo-Path.modified.3
index 858afb2c..f85d1e7f 100644
--- a/man/man3/tomo-Path.modified.3
+++ b/man/man3/tomo-Path.modified.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.modified 3 2025-04-21 "Tomo man-pages"
+.TH Path.modified 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.modified \- get file modification time
.SH LIBRARY
diff --git a/man/man3/tomo-Path.owner.3 b/man/man3/tomo-Path.owner.3
index c0523f62..14ade273 100644
--- a/man/man3/tomo-Path.owner.3
+++ b/man/man3/tomo-Path.owner.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.owner 3 2025-04-21 "Tomo man-pages"
+.TH Path.owner 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.owner \- get file owner
.SH LIBRARY
diff --git a/man/man3/tomo-Path.parent.3 b/man/man3/tomo-Path.parent.3
index a23679cc..9f3fa3c8 100644
--- a/man/man3/tomo-Path.parent.3
+++ b/man/man3/tomo-Path.parent.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.parent 3 2025-04-21 "Tomo man-pages"
+.TH Path.parent 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.parent \- get parent directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.read.3 b/man/man3/tomo-Path.read.3
index 6a594077..a4d5a11e 100644
--- a/man/man3/tomo-Path.read.3
+++ b/man/man3/tomo-Path.read.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.read 3 2025-04-21 "Tomo man-pages"
+.TH Path.read 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.read \- read file contents
.SH LIBRARY
diff --git a/man/man3/tomo-Path.read_bytes.3 b/man/man3/tomo-Path.read_bytes.3
index b4c5f922..98a2f848 100644
--- a/man/man3/tomo-Path.read_bytes.3
+++ b/man/man3/tomo-Path.read_bytes.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.read_bytes 3 2025-04-21 "Tomo man-pages"
+.TH Path.read_bytes 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.read_bytes \- read file contents as bytes
.SH LIBRARY
diff --git a/man/man3/tomo-Path.relative_to.3 b/man/man3/tomo-Path.relative_to.3
index 399ec4e5..2e800594 100644
--- a/man/man3/tomo-Path.relative_to.3
+++ b/man/man3/tomo-Path.relative_to.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.relative_to 3 2025-04-21 "Tomo man-pages"
+.TH Path.relative_to 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.relative_to \- apply a relative path to another
.SH LIBRARY
diff --git a/man/man3/tomo-Path.remove.3 b/man/man3/tomo-Path.remove.3
index 598a7286..fcb1e87b 100644
--- a/man/man3/tomo-Path.remove.3
+++ b/man/man3/tomo-Path.remove.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.remove 3 2025-04-21 "Tomo man-pages"
+.TH Path.remove 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.remove \- remove a file or directory
.SH LIBRARY
diff --git a/man/man3/tomo-Path.resolved.3 b/man/man3/tomo-Path.resolved.3
index 99f41b59..4367127a 100644
--- a/man/man3/tomo-Path.resolved.3
+++ b/man/man3/tomo-Path.resolved.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.resolved 3 2025-04-21 "Tomo man-pages"
+.TH Path.resolved 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.resolved \- resolve a path
.SH LIBRARY
diff --git a/man/man3/tomo-Path.set_owner.3 b/man/man3/tomo-Path.set_owner.3
index de640d0d..61f4d9c6 100644
--- a/man/man3/tomo-Path.set_owner.3
+++ b/man/man3/tomo-Path.set_owner.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.set_owner 3 2025-04-21 "Tomo man-pages"
+.TH Path.set_owner 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.set_owner \- set the owner
.SH LIBRARY
diff --git a/man/man3/tomo-Path.subdirectories.3 b/man/man3/tomo-Path.subdirectories.3
index 41c4a2a2..9510b916 100644
--- a/man/man3/tomo-Path.subdirectories.3
+++ b/man/man3/tomo-Path.subdirectories.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.subdirectories 3 2025-04-21 "Tomo man-pages"
+.TH Path.subdirectories 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.subdirectories \- get subdirectories
.SH LIBRARY
diff --git a/man/man3/tomo-Path.unique_directory.3 b/man/man3/tomo-Path.unique_directory.3
index 765824b4..e7a311cc 100644
--- a/man/man3/tomo-Path.unique_directory.3
+++ b/man/man3/tomo-Path.unique_directory.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.unique_directory 3 2025-04-21 "Tomo man-pages"
+.TH Path.unique_directory 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.unique_directory \- create a directory with a unique name
.SH LIBRARY
diff --git a/man/man3/tomo-Path.write.3 b/man/man3/tomo-Path.write.3
index b3fdc3ef..1735f393 100644
--- a/man/man3/tomo-Path.write.3
+++ b/man/man3/tomo-Path.write.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.write 3 2025-04-21 "Tomo man-pages"
+.TH Path.write 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.write \- write to a file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.write_bytes.3 b/man/man3/tomo-Path.write_bytes.3
index e188e08b..a4b5a5ff 100644
--- a/man/man3/tomo-Path.write_bytes.3
+++ b/man/man3/tomo-Path.write_bytes.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.write_bytes 3 2025-04-21 "Tomo man-pages"
+.TH Path.write_bytes 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.write_bytes \- write bytes to a file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.write_unique.3 b/man/man3/tomo-Path.write_unique.3
index 002e851c..7093206b 100644
--- a/man/man3/tomo-Path.write_unique.3
+++ b/man/man3/tomo-Path.write_unique.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.write_unique 3 2025-04-21 "Tomo man-pages"
+.TH Path.write_unique 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.write_unique \- write to a uniquely named file
.SH LIBRARY
diff --git a/man/man3/tomo-Path.write_unique_bytes.3 b/man/man3/tomo-Path.write_unique_bytes.3
index cc4df9cd..589d7d66 100644
--- a/man/man3/tomo-Path.write_unique_bytes.3
+++ b/man/man3/tomo-Path.write_unique_bytes.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Path.write_unique_bytes 3 2025-04-21 "Tomo man-pages"
+.TH Path.write_unique_bytes 3 2025-04-27 "Tomo man-pages"
.SH NAME
Path.write_unique_bytes \- write bytes to a uniquely named file
.SH LIBRARY
diff --git a/man/man3/tomo-Set.add.3 b/man/man3/tomo-Set.add.3
index af273e88..130fc6fc 100644
--- a/man/man3/tomo-Set.add.3
+++ b/man/man3/tomo-Set.add.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.add 3 2025-04-21 "Tomo man-pages"
+.TH Set.add 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.add \- add item to a set
.SH LIBRARY
diff --git a/man/man3/tomo-Set.add_all.3 b/man/man3/tomo-Set.add_all.3
index 701ac084..be32873b 100644
--- a/man/man3/tomo-Set.add_all.3
+++ b/man/man3/tomo-Set.add_all.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.add_all 3 2025-04-21 "Tomo man-pages"
+.TH Set.add_all 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.add_all \- add items to a set
.SH LIBRARY
diff --git a/man/man3/tomo-Set.clear.3 b/man/man3/tomo-Set.clear.3
index fbd931f5..66396f7f 100644
--- a/man/man3/tomo-Set.clear.3
+++ b/man/man3/tomo-Set.clear.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.clear 3 2025-04-21 "Tomo man-pages"
+.TH Set.clear 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.clear \- clear a set
.SH LIBRARY
diff --git a/man/man3/tomo-Set.has.3 b/man/man3/tomo-Set.has.3
index d76550f2..5d819ede 100644
--- a/man/man3/tomo-Set.has.3
+++ b/man/man3/tomo-Set.has.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.has 3 2025-04-21 "Tomo man-pages"
+.TH Set.has 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.has \- check if a set has an item
.SH LIBRARY
diff --git a/man/man3/tomo-Set.is_subset_of.3 b/man/man3/tomo-Set.is_subset_of.3
index 201cc467..2af13993 100644
--- a/man/man3/tomo-Set.is_subset_of.3
+++ b/man/man3/tomo-Set.is_subset_of.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.is_subset_of 3 2025-04-21 "Tomo man-pages"
+.TH Set.is_subset_of 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.is_subset_of \- check if a set is a subset
.SH LIBRARY
diff --git a/man/man3/tomo-Set.is_superset_of.3 b/man/man3/tomo-Set.is_superset_of.3
index 87e587c1..6c2c2294 100644
--- a/man/man3/tomo-Set.is_superset_of.3
+++ b/man/man3/tomo-Set.is_superset_of.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.is_superset_of 3 2025-04-21 "Tomo man-pages"
+.TH Set.is_superset_of 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.is_superset_of \- check if a set is a superset
.SH LIBRARY
diff --git a/man/man3/tomo-Set.overlap.3 b/man/man3/tomo-Set.overlap.3
index 032dfc74..9c2843f0 100644
--- a/man/man3/tomo-Set.overlap.3
+++ b/man/man3/tomo-Set.overlap.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.overlap 3 2025-04-21 "Tomo man-pages"
+.TH Set.overlap 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.overlap \- set intersection
.SH LIBRARY
diff --git a/man/man3/tomo-Set.remove.3 b/man/man3/tomo-Set.remove.3
index 55fedf96..34d54bec 100644
--- a/man/man3/tomo-Set.remove.3
+++ b/man/man3/tomo-Set.remove.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.remove 3 2025-04-21 "Tomo man-pages"
+.TH Set.remove 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.remove \- remove an item from a set
.SH LIBRARY
diff --git a/man/man3/tomo-Set.remove_all.3 b/man/man3/tomo-Set.remove_all.3
index cf7a5bce..749d73c7 100644
--- a/man/man3/tomo-Set.remove_all.3
+++ b/man/man3/tomo-Set.remove_all.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.remove_all 3 2025-04-21 "Tomo man-pages"
+.TH Set.remove_all 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.remove_all \- remove items from a set
.SH LIBRARY
diff --git a/man/man3/tomo-Set.with.3 b/man/man3/tomo-Set.with.3
index 21d54ac8..ec0ccf48 100644
--- a/man/man3/tomo-Set.with.3
+++ b/man/man3/tomo-Set.with.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.with 3 2025-04-21 "Tomo man-pages"
+.TH Set.with 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.with \- set union
.SH LIBRARY
diff --git a/man/man3/tomo-Set.without.3 b/man/man3/tomo-Set.without.3
index 4e2ca251..72af3f1a 100644
--- a/man/man3/tomo-Set.without.3
+++ b/man/man3/tomo-Set.without.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Set.without 3 2025-04-21 "Tomo man-pages"
+.TH Set.without 3 2025-04-27 "Tomo man-pages"
.SH NAME
Set.without \- set difference
.SH LIBRARY
diff --git a/man/man3/tomo-Table.clear.3 b/man/man3/tomo-Table.clear.3
index d76e3b47..e012e4b1 100644
--- a/man/man3/tomo-Table.clear.3
+++ b/man/man3/tomo-Table.clear.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Table.clear 3 2025-04-21 "Tomo man-pages"
+.TH Table.clear 3 2025-04-27 "Tomo man-pages"
.SH NAME
Table.clear \- clear a table
.SH LIBRARY
diff --git a/man/man3/tomo-Table.get.3 b/man/man3/tomo-Table.get.3
index e1ab5fdb..e26d3670 100644
--- a/man/man3/tomo-Table.get.3
+++ b/man/man3/tomo-Table.get.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Table.get 3 2025-04-21 "Tomo man-pages"
+.TH Table.get 3 2025-04-27 "Tomo man-pages"
.SH NAME
Table.get \- get an item from a table
.SH LIBRARY
diff --git a/man/man3/tomo-Table.get_or_set.3 b/man/man3/tomo-Table.get_or_set.3
index c112671c..6f59684b 100644
--- a/man/man3/tomo-Table.get_or_set.3
+++ b/man/man3/tomo-Table.get_or_set.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Table.get_or_set 3 2025-04-21 "Tomo man-pages"
+.TH Table.get_or_set 3 2025-04-27 "Tomo man-pages"
.SH NAME
Table.get_or_set \- get an item or set a default if absent
.SH LIBRARY
diff --git a/man/man3/tomo-Table.has.3 b/man/man3/tomo-Table.has.3
index e6152d5f..f08fccb4 100644
--- a/man/man3/tomo-Table.has.3
+++ b/man/man3/tomo-Table.has.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Table.has 3 2025-04-21 "Tomo man-pages"
+.TH Table.has 3 2025-04-27 "Tomo man-pages"
.SH NAME
Table.has \- check for a key
.SH LIBRARY
diff --git a/man/man3/tomo-Table.remove.3 b/man/man3/tomo-Table.remove.3
index 6da1dfdb..50ac14ff 100644
--- a/man/man3/tomo-Table.remove.3
+++ b/man/man3/tomo-Table.remove.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Table.remove 3 2025-04-21 "Tomo man-pages"
+.TH Table.remove 3 2025-04-27 "Tomo man-pages"
.SH NAME
Table.remove \- remove a table entry
.SH LIBRARY
diff --git a/man/man3/tomo-Table.set.3 b/man/man3/tomo-Table.set.3
index 89ae5415..f7e02ceb 100644
--- a/man/man3/tomo-Table.set.3
+++ b/man/man3/tomo-Table.set.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Table.set 3 2025-04-21 "Tomo man-pages"
+.TH Table.set 3 2025-04-27 "Tomo man-pages"
.SH NAME
Table.set \- set a table entry
.SH LIBRARY
diff --git a/man/man3/tomo-Text.as_c_string.3 b/man/man3/tomo-Text.as_c_string.3
index 1e86ebf9..d4d8885f 100644
--- a/man/man3/tomo-Text.as_c_string.3
+++ b/man/man3/tomo-Text.as_c_string.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.as_c_string 3 2025-04-21 "Tomo man-pages"
+.TH Text.as_c_string 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.as_c_string \- convert to C-style string
.SH LIBRARY
diff --git a/man/man3/tomo-Text.at.3 b/man/man3/tomo-Text.at.3
index abdb8cce..0b658a84 100644
--- a/man/man3/tomo-Text.at.3
+++ b/man/man3/tomo-Text.at.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.at 3 2025-04-21 "Tomo man-pages"
+.TH Text.at 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.at \- get a letter
.SH LIBRARY
diff --git a/man/man3/tomo-Text.by_line.3 b/man/man3/tomo-Text.by_line.3
index 2634d854..27204aaa 100644
--- a/man/man3/tomo-Text.by_line.3
+++ b/man/man3/tomo-Text.by_line.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.by_line 3 2025-04-21 "Tomo man-pages"
+.TH Text.by_line 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.by_line \- iterate by line
.SH LIBRARY
diff --git a/man/man3/tomo-Text.by_split.3 b/man/man3/tomo-Text.by_split.3
index cd0b7027..92527f51 100644
--- a/man/man3/tomo-Text.by_split.3
+++ b/man/man3/tomo-Text.by_split.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.by_split 3 2025-04-21 "Tomo man-pages"
+.TH Text.by_split 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.by_split \- iterate by a spliting text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.by_split_any.3 b/man/man3/tomo-Text.by_split_any.3
index f7d6c0ca..67b6c1e9 100644
--- a/man/man3/tomo-Text.by_split_any.3
+++ b/man/man3/tomo-Text.by_split_any.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.by_split_any 3 2025-04-21 "Tomo man-pages"
+.TH Text.by_split_any 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.by_split_any \- iterate by one of many splitting characters
.SH LIBRARY
diff --git a/man/man3/tomo-Text.bytes.3 b/man/man3/tomo-Text.bytes.3
index 470f8541..a49b598d 100644
--- a/man/man3/tomo-Text.bytes.3
+++ b/man/man3/tomo-Text.bytes.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.bytes 3 2025-04-21 "Tomo man-pages"
+.TH Text.bytes 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.bytes \- get UTF8 bytes
.SH LIBRARY
diff --git a/man/man3/tomo-Text.caseless_equals.3 b/man/man3/tomo-Text.caseless_equals.3
index 884bcb0b..0df8acc9 100644
--- a/man/man3/tomo-Text.caseless_equals.3
+++ b/man/man3/tomo-Text.caseless_equals.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.caseless_equals 3 2025-04-21 "Tomo man-pages"
+.TH Text.caseless_equals 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.caseless_equals \- case-insensitive comparison
.SH LIBRARY
diff --git a/man/man3/tomo-Text.codepoint_names.3 b/man/man3/tomo-Text.codepoint_names.3
index 52f8dd87..3a8520f7 100644
--- a/man/man3/tomo-Text.codepoint_names.3
+++ b/man/man3/tomo-Text.codepoint_names.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.codepoint_names 3 2025-04-21 "Tomo man-pages"
+.TH Text.codepoint_names 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.codepoint_names \- get unicode codepoint names
.SH LIBRARY
diff --git a/man/man3/tomo-Text.ends_with.3 b/man/man3/tomo-Text.ends_with.3
index e071f70d..cf0a5d01 100644
--- a/man/man3/tomo-Text.ends_with.3
+++ b/man/man3/tomo-Text.ends_with.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.ends_with 3 2025-04-21 "Tomo man-pages"
+.TH Text.ends_with 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.ends_with \- check suffix
.SH LIBRARY
diff --git a/man/man3/tomo-Text.from.3 b/man/man3/tomo-Text.from.3
index e8fdfd69..347184eb 100644
--- a/man/man3/tomo-Text.from.3
+++ b/man/man3/tomo-Text.from.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.from 3 2025-04-21 "Tomo man-pages"
+.TH Text.from 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.from \- slice from a starting index
.SH LIBRARY
diff --git a/man/man3/tomo-Text.from_bytes.3 b/man/man3/tomo-Text.from_bytes.3
index 892abe60..615eb3a7 100644
--- a/man/man3/tomo-Text.from_bytes.3
+++ b/man/man3/tomo-Text.from_bytes.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.from_bytes 3 2025-04-21 "Tomo man-pages"
+.TH Text.from_bytes 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.from_bytes \- convert UTF8 byte list to text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.from_c_string.3 b/man/man3/tomo-Text.from_c_string.3
index c7d620c2..addc26c5 100644
--- a/man/man3/tomo-Text.from_c_string.3
+++ b/man/man3/tomo-Text.from_c_string.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.from_c_string 3 2025-04-21 "Tomo man-pages"
+.TH Text.from_c_string 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.from_c_string \- convert C-style string to text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.from_codepoint_names.3 b/man/man3/tomo-Text.from_codepoint_names.3
index 1f4b48c0..33482533 100644
--- a/man/man3/tomo-Text.from_codepoint_names.3
+++ b/man/man3/tomo-Text.from_codepoint_names.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.from_codepoint_names 3 2025-04-21 "Tomo man-pages"
+.TH Text.from_codepoint_names 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.from_codepoint_names \- convert list of unicode codepoint names to text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.from_codepoints.3 b/man/man3/tomo-Text.from_codepoints.3
index 7643495b..cf99b7f1 100644
--- a/man/man3/tomo-Text.from_codepoints.3
+++ b/man/man3/tomo-Text.from_codepoints.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.from_codepoints 3 2025-04-21 "Tomo man-pages"
+.TH Text.from_codepoints 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.from_codepoints \- convert UTF32 codepoints to text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.has.3 b/man/man3/tomo-Text.has.3
index dfd9257f..48d5ad41 100644
--- a/man/man3/tomo-Text.has.3
+++ b/man/man3/tomo-Text.has.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.has 3 2025-04-21 "Tomo man-pages"
+.TH Text.has 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.has \- check for substring
.SH LIBRARY
diff --git a/man/man3/tomo-Text.join.3 b/man/man3/tomo-Text.join.3
index 8c794f6f..22ef7e5f 100644
--- a/man/man3/tomo-Text.join.3
+++ b/man/man3/tomo-Text.join.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.join 3 2025-04-21 "Tomo man-pages"
+.TH Text.join 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.join \- concatenate with separator
.SH LIBRARY
diff --git a/man/man3/tomo-Text.left_pad.3 b/man/man3/tomo-Text.left_pad.3
index 516092ec..bc760879 100644
--- a/man/man3/tomo-Text.left_pad.3
+++ b/man/man3/tomo-Text.left_pad.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.left_pad 3 2025-04-21 "Tomo man-pages"
+.TH Text.left_pad 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.left_pad \- left-pad text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.lines.3 b/man/man3/tomo-Text.lines.3
index 52391e80..1d9216ff 100644
--- a/man/man3/tomo-Text.lines.3
+++ b/man/man3/tomo-Text.lines.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.lines 3 2025-04-21 "Tomo man-pages"
+.TH Text.lines 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.lines \- get list of lines
.SH LIBRARY
diff --git a/man/man3/tomo-Text.lower.3 b/man/man3/tomo-Text.lower.3
index d2747809..05acdecc 100644
--- a/man/man3/tomo-Text.lower.3
+++ b/man/man3/tomo-Text.lower.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.lower 3 2025-04-21 "Tomo man-pages"
+.TH Text.lower 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.lower \- convert to lowercase
.SH LIBRARY
diff --git a/man/man3/tomo-Text.middle_pad.3 b/man/man3/tomo-Text.middle_pad.3
index c2fad231..f624ec16 100644
--- a/man/man3/tomo-Text.middle_pad.3
+++ b/man/man3/tomo-Text.middle_pad.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.middle_pad 3 2025-04-21 "Tomo man-pages"
+.TH Text.middle_pad 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.middle_pad \- pad text, centered
.SH LIBRARY
diff --git a/man/man3/tomo-Text.quoted.3 b/man/man3/tomo-Text.quoted.3
index 32859bc6..bae4f235 100644
--- a/man/man3/tomo-Text.quoted.3
+++ b/man/man3/tomo-Text.quoted.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.quoted 3 2025-04-21 "Tomo man-pages"
+.TH Text.quoted 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.quoted \- add quotation marks and escapes
.SH LIBRARY
diff --git a/man/man3/tomo-Text.repeat.3 b/man/man3/tomo-Text.repeat.3
index d3db6dba..504c9065 100644
--- a/man/man3/tomo-Text.repeat.3
+++ b/man/man3/tomo-Text.repeat.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.repeat 3 2025-04-21 "Tomo man-pages"
+.TH Text.repeat 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.repeat \- repeat text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.replace.3 b/man/man3/tomo-Text.replace.3
index b9224775..0566fbca 100644
--- a/man/man3/tomo-Text.replace.3
+++ b/man/man3/tomo-Text.replace.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.replace 3 2025-04-21 "Tomo man-pages"
+.TH Text.replace 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.replace \- replace a substring
.SH LIBRARY
diff --git a/man/man3/tomo-Text.reversed.3 b/man/man3/tomo-Text.reversed.3
index 7855dca1..e453cf12 100644
--- a/man/man3/tomo-Text.reversed.3
+++ b/man/man3/tomo-Text.reversed.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.reversed 3 2025-04-21 "Tomo man-pages"
+.TH Text.reversed 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.reversed \- get a reversed copy
.SH LIBRARY
diff --git a/man/man3/tomo-Text.right_pad.3 b/man/man3/tomo-Text.right_pad.3
index eb517c26..4516e6bd 100644
--- a/man/man3/tomo-Text.right_pad.3
+++ b/man/man3/tomo-Text.right_pad.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.right_pad 3 2025-04-21 "Tomo man-pages"
+.TH Text.right_pad 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.right_pad \- right-pad text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.slice.3 b/man/man3/tomo-Text.slice.3
index 399fbb42..c6045e43 100644
--- a/man/man3/tomo-Text.slice.3
+++ b/man/man3/tomo-Text.slice.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.slice 3 2025-04-21 "Tomo man-pages"
+.TH Text.slice 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.slice \- get a slice of a text
.SH LIBRARY
diff --git a/man/man3/tomo-Text.split.3 b/man/man3/tomo-Text.split.3
index ea1f0d1d..b94a787c 100644
--- a/man/man3/tomo-Text.split.3
+++ b/man/man3/tomo-Text.split.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.split 3 2025-04-21 "Tomo man-pages"
+.TH Text.split 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.split \- split a text by a delimiter
.SH LIBRARY
diff --git a/man/man3/tomo-Text.split_any.3 b/man/man3/tomo-Text.split_any.3
index 65b5f322..0b26c3d6 100644
--- a/man/man3/tomo-Text.split_any.3
+++ b/man/man3/tomo-Text.split_any.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.split_any 3 2025-04-21 "Tomo man-pages"
+.TH Text.split_any 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.split_any \- split a text by multiple delimiters
.SH LIBRARY
diff --git a/man/man3/tomo-Text.starts_with.3 b/man/man3/tomo-Text.starts_with.3
index 2da2bacd..57ea412e 100644
--- a/man/man3/tomo-Text.starts_with.3
+++ b/man/man3/tomo-Text.starts_with.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.starts_with 3 2025-04-21 "Tomo man-pages"
+.TH Text.starts_with 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.starts_with \- check prefix
.SH LIBRARY
diff --git a/man/man3/tomo-Text.title.3 b/man/man3/tomo-Text.title.3
index 811d1547..7f2d5326 100644
--- a/man/man3/tomo-Text.title.3
+++ b/man/man3/tomo-Text.title.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.title 3 2025-04-21 "Tomo man-pages"
+.TH Text.title 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.title \- titlecase
.SH LIBRARY
diff --git a/man/man3/tomo-Text.to.3 b/man/man3/tomo-Text.to.3
index 9a5d76d0..14de06d4 100644
--- a/man/man3/tomo-Text.to.3
+++ b/man/man3/tomo-Text.to.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.to 3 2025-04-21 "Tomo man-pages"
+.TH Text.to 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.to \- slice to an end index
.SH LIBRARY
diff --git a/man/man3/tomo-Text.translate.3 b/man/man3/tomo-Text.translate.3
index dbf3ed89..3c6b84e5 100644
--- a/man/man3/tomo-Text.translate.3
+++ b/man/man3/tomo-Text.translate.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.translate 3 2025-04-21 "Tomo man-pages"
+.TH Text.translate 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.translate \- perform multiple replacements
.SH LIBRARY
diff --git a/man/man3/tomo-Text.trim.3 b/man/man3/tomo-Text.trim.3
index df1cbb43..c2298654 100644
--- a/man/man3/tomo-Text.trim.3
+++ b/man/man3/tomo-Text.trim.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.trim 3 2025-04-21 "Tomo man-pages"
+.TH Text.trim 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.trim \- trim characters
.SH LIBRARY
diff --git a/man/man3/tomo-Text.upper.3 b/man/man3/tomo-Text.upper.3
index 7e962cd0..b06ca61c 100644
--- a/man/man3/tomo-Text.upper.3
+++ b/man/man3/tomo-Text.upper.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.upper 3 2025-04-21 "Tomo man-pages"
+.TH Text.upper 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.upper \- uppercase
.SH LIBRARY
diff --git a/man/man3/tomo-Text.utf32_codepoints.3 b/man/man3/tomo-Text.utf32_codepoints.3
index 00f4a6c5..93982a4e 100644
--- a/man/man3/tomo-Text.utf32_codepoints.3
+++ b/man/man3/tomo-Text.utf32_codepoints.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.utf32_codepoints 3 2025-04-21 "Tomo man-pages"
+.TH Text.utf32_codepoints 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.utf32_codepoints \- get UTF32 codepoints
.SH LIBRARY
diff --git a/man/man3/tomo-Text.width.3 b/man/man3/tomo-Text.width.3
index ce9b4385..c11534a0 100644
--- a/man/man3/tomo-Text.width.3
+++ b/man/man3/tomo-Text.width.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.width 3 2025-04-21 "Tomo man-pages"
+.TH Text.width 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.width \- get display width
.SH LIBRARY
diff --git a/man/man3/tomo-Text.without_prefix.3 b/man/man3/tomo-Text.without_prefix.3
index 0ee2e455..4eef27f0 100644
--- a/man/man3/tomo-Text.without_prefix.3
+++ b/man/man3/tomo-Text.without_prefix.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.without_prefix 3 2025-04-21 "Tomo man-pages"
+.TH Text.without_prefix 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.without_prefix \- remove prefix
.SH LIBRARY
diff --git a/man/man3/tomo-Text.without_suffix.3 b/man/man3/tomo-Text.without_suffix.3
index e008133c..1f46556e 100644
--- a/man/man3/tomo-Text.without_suffix.3
+++ b/man/man3/tomo-Text.without_suffix.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH Text.without_suffix 3 2025-04-21 "Tomo man-pages"
+.TH Text.without_suffix 3 2025-04-27 "Tomo man-pages"
.SH NAME
Text.without_suffix \- remove suffix
.SH LIBRARY
diff --git a/man/man3/tomo-USE_COLOR.3 b/man/man3/tomo-USE_COLOR.3
index 297166e9..8f05e974 100644
--- a/man/man3/tomo-USE_COLOR.3
+++ b/man/man3/tomo-USE_COLOR.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH USE_COLOR 3 2025-04-21 "Tomo man-pages"
+.TH USE_COLOR 3 2025-04-27 "Tomo man-pages"
.SH NAME
USE_COLOR \- whether to use colors
.SH LIBRARY
diff --git a/man/man3/tomo-ask.3 b/man/man3/tomo-ask.3
index 0303d062..e78090f9 100644
--- a/man/man3/tomo-ask.3
+++ b/man/man3/tomo-ask.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH ask 3 2025-04-21 "Tomo man-pages"
+.TH ask 3 2025-04-27 "Tomo man-pages"
.SH NAME
ask \- get user input
.SH LIBRARY
diff --git a/man/man3/tomo-exit.3 b/man/man3/tomo-exit.3
index 2c235c3a..b9e83d82 100644
--- a/man/man3/tomo-exit.3
+++ b/man/man3/tomo-exit.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH exit 3 2025-04-21 "Tomo man-pages"
+.TH exit 3 2025-04-27 "Tomo man-pages"
.SH NAME
exit \- exit the program
.SH LIBRARY
diff --git a/man/man3/tomo-fail.3 b/man/man3/tomo-fail.3
index 25f6f135..789af977 100644
--- a/man/man3/tomo-fail.3
+++ b/man/man3/tomo-fail.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH fail 3 2025-04-21 "Tomo man-pages"
+.TH fail 3 2025-04-27 "Tomo man-pages"
.SH NAME
fail \- abort the program
.SH LIBRARY
diff --git a/man/man3/tomo-getenv.3 b/man/man3/tomo-getenv.3
index 45ee630b..5f4f1fba 100644
--- a/man/man3/tomo-getenv.3
+++ b/man/man3/tomo-getenv.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH getenv 3 2025-04-21 "Tomo man-pages"
+.TH getenv 3 2025-04-27 "Tomo man-pages"
.SH NAME
getenv \- get an environment variable
.SH LIBRARY
diff --git a/man/man3/tomo-print.3 b/man/man3/tomo-print.3
index 7c328fc8..88f2362c 100644
--- a/man/man3/tomo-print.3
+++ b/man/man3/tomo-print.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH print 3 2025-04-21 "Tomo man-pages"
+.TH print 3 2025-04-27 "Tomo man-pages"
.SH NAME
print \- print some text
.SH LIBRARY
diff --git a/man/man3/tomo-say.3 b/man/man3/tomo-say.3
index db6106a9..4a74781b 100644
--- a/man/man3/tomo-say.3
+++ b/man/man3/tomo-say.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH say 3 2025-04-21 "Tomo man-pages"
+.TH say 3 2025-04-27 "Tomo man-pages"
.SH NAME
say \- print some text
.SH LIBRARY
diff --git a/man/man3/tomo-setenv.3 b/man/man3/tomo-setenv.3
index 4437fb20..fc0fb258 100644
--- a/man/man3/tomo-setenv.3
+++ b/man/man3/tomo-setenv.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH setenv 3 2025-04-21 "Tomo man-pages"
+.TH setenv 3 2025-04-27 "Tomo man-pages"
.SH NAME
setenv \- set an environment variable
.SH LIBRARY
diff --git a/man/man3/tomo-sleep.3 b/man/man3/tomo-sleep.3
index 213ea167..3a77bf84 100644
--- a/man/man3/tomo-sleep.3
+++ b/man/man3/tomo-sleep.3
@@ -2,7 +2,7 @@
.\" Copyright (c) 2025 Bruce Hill
.\" All rights reserved.
.\"
-.TH sleep 3 2025-04-21 "Tomo man-pages"
+.TH sleep 3 2025-04-27 "Tomo man-pages"
.SH NAME
sleep \- wait for an interval
.SH LIBRARY
diff --git a/scripts/mandoc_gen.py b/scripts/mandoc_gen.py
index 66dedd1f..8342e253 100755
--- a/scripts/mandoc_gen.py
+++ b/scripts/mandoc_gen.py
@@ -118,6 +118,7 @@ if __name__ == "__main__":
if len(sys.argv) > 1:
all_files = ""
for filename in sys.argv[1:]:
+ print(f"Making mandoc for {filename}")
with open(filename, "r") as f:
all_files += f.read()
convert_to_markdown(all_files)
diff --git a/src/environment.c b/src/environment.c
index 8bf77733..290ebe12 100644
--- a/src/environment.c
+++ b/src/environment.c
@@ -102,7 +102,6 @@ env_t *global_env(bool source_mapping)
{"clamped", "Int$clamped", "func(x,low,high:Int -> Int)"},
{"divided_by", "Int$divided_by", "func(x,y:Int -> Int)"},
{"factorial", "Int$factorial", "func(x:Int -> Int)"},
- {"format", "Int$format", "func(i:Int, digits=0 -> Text)"},
{"gcd", "Int$gcd", "func(x,y:Int -> Int)"},
{"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes -> Text)"},
{"is_between", "Int$is_between", "func(x:Int,low:Int,high:Int -> Bool)"},
@@ -134,7 +133,6 @@ env_t *global_env(bool source_mapping)
{"bits", "Int64$bits", "func(x:Int64 -> [Bool])"},
{"clamped", "Int64$clamped", "func(x,low,high:Int64 -> Int64)"},
{"divided_by", "Int64$divided_by", "func(x,y:Int64 -> Int64)"},
- {"format", "Int64$format", "func(i:Int64, digits=0 -> Text)"},
{"gcd", "Int64$gcd", "func(x,y:Int64 -> Int64)"},
{"parse", "Int64$parse", "func(text:Text -> Int64?)"},
{"hex", "Int64$hex", "func(i:Int64, digits=0, uppercase=yes, prefix=yes -> Text)"},
@@ -156,7 +154,6 @@ env_t *global_env(bool source_mapping)
{"bits", "Int32$bits", "func(x:Int32 -> [Bool])"},
{"clamped", "Int32$clamped", "func(x,low,high:Int32 -> Int32)"},
{"divided_by", "Int32$divided_by", "func(x,y:Int32 -> Int32)"},
- {"format", "Int32$format", "func(i:Int32, digits=0 -> Text)"},
{"gcd", "Int32$gcd", "func(x,y:Int32 -> Int32)"},
{"parse", "Int32$parse", "func(text:Text -> Int32?)"},
{"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes -> Text)"},
@@ -178,7 +175,6 @@ env_t *global_env(bool source_mapping)
{"bits", "Int16$bits", "func(x:Int16 -> [Bool])"},
{"clamped", "Int16$clamped", "func(x,low,high:Int16 -> Int16)"},
{"divided_by", "Int16$divided_by", "func(x,y:Int16 -> Int16)"},
- {"format", "Int16$format", "func(i:Int16, digits=0 -> Text)"},
{"gcd", "Int16$gcd", "func(x,y:Int16 -> Int16)"},
{"parse", "Int16$parse", "func(text:Text -> Int16?)"},
{"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes -> Text)"},
@@ -200,7 +196,6 @@ env_t *global_env(bool source_mapping)
{"bits", "Int8$bits", "func(x:Int8 -> [Bool])"},
{"clamped", "Int8$clamped", "func(x,low,high:Int8 -> Int8)"},
{"divided_by", "Int8$divided_by", "func(x,y:Int8 -> Int8)"},
- {"format", "Int8$format", "func(i:Int8, digits=0 -> Text)"},
{"gcd", "Int8$gcd", "func(x,y:Int8 -> Int8)"},
{"parse", "Int8$parse", "func(text:Text -> Int8?)"},
{"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes -> Text)"},
@@ -224,9 +219,8 @@ env_t *global_env(bool source_mapping)
{"Num", Type(NumType, .bits=TYPE_NBITS64), "Num_t", "Num$info", TypedList(ns_entry_t,
{"near", "Num$near", "func(x,y:Num, ratio=1e-9, min_epsilon=1e-9 -> Bool)"},
{"clamped", "Num$clamped", "func(x,low,high:Num -> Num)"},
- {"format", "Num$format", "func(n:Num, precision=16 -> Text)"},
- {"scientific", "Num$scientific", "func(n:Num,precision=0 -> Text)"},
- {"percent", "Num$percent", "func(n:Num,precision=0 -> Text)"},
+ {"percent", "Num$percent", "func(n:Num,precision=0.01 -> Text)"},
+ {"with_precision", "Num$with_precision", "func(n:Num,precision:Num -> Num)"},
{"is_between", "Num$is_between", "func(x:Num,low:Num,high:Num -> Bool)"},
{"isinf", "Num$isinf", "func(n:Num -> Bool)"},
{"isfinite", "Num$isfinite", "func(n:Num -> Bool)"},
@@ -257,9 +251,8 @@ env_t *global_env(bool source_mapping)
{"Num32", Type(NumType, .bits=TYPE_NBITS32), "Num32_t", "Num32$info", TypedList(ns_entry_t,
{"near", "Num32$near", "func(x,y:Num32, ratio=Num32(1e-9), min_epsilon=Num32(1e-9) -> Bool)"},
{"clamped", "Num32$clamped", "func(x,low,high:Num32 -> Num32)"},
- {"format", "Num32$format", "func(n:Num32, precision=8 -> Text)"},
- {"scientific", "Num32$scientific", "func(n:Num32, precision=0 -> Text)"},
- {"percent", "Num32$percent", "func(n:Num32,precision=0 -> Text)"},
+ {"percent", "Num32$percent", "func(n:Num32,precision=Num32(.01) -> Text)"},
+ {"with_precision", "Num32$with_precision", "func(n:Num32,precision:Num32 -> Num32)"},
{"is_between", "Num32$is_between", "func(x:Num32,low:Num32,high:Num32 -> Bool)"},
{"isinf", "Num32$isinf", "func(n:Num32 -> Bool)"},
{"isfinite", "Num32$isfinite", "func(n:Num32 -> Bool)"},
@@ -280,7 +273,7 @@ env_t *global_env(bool source_mapping)
F2(atan2), F2(copysign), F2(fdim), F2(hypot), F2(nextafter),
)},
{"CString", Type(CStringType), "char*", "CString$info", TypedList(ns_entry_t,
- {"as_text", "CString$as_text_simple", "func(str:CString -> Text)"},
+ {"as_text", "Text$from_str", "func(str:CString -> Text)"},
)},
#undef F2
#undef F_opt
diff --git a/src/stdlib/bytes.c b/src/stdlib/bytes.c
index fffce06c..5605b2c8 100644
--- a/src/stdlib/bytes.c
+++ b/src/stdlib/bytes.c
@@ -14,7 +14,15 @@ PUREFUNC public Text_t Byte$as_text(const void *b, bool colorize, const TypeInfo
{
(void)info;
if (!b) return Text("Byte");
- return Text$format(colorize ? "\x1b[35m0x%02X\x1b[m" : "0x%02X", *(Byte_t*)b);
+ Byte_t byte = *(Byte_t*)b;
+ char digits[] = {'0', 'x',
+ (byte / 16) <= 9 ? '0' + (byte / 16) : 'a' + (byte / 16) - 10,
+ (byte & 15) <= 9 ? '0' + (byte & 15) : 'a' + (byte & 15) - 10,
+ '\0',
+ };
+ Text_t text = Text$from_str(digits);
+ if (colorize) text = Texts(Text("\x1b[35m"), text, Text("\x1b[m"));
+ return text;
}
public CONSTFUNC bool Byte$is_between(const Byte_t x, const Byte_t low, const Byte_t high) {
@@ -24,14 +32,20 @@ public CONSTFUNC bool Byte$is_between(const Byte_t x, const Byte_t low, const By
public Text_t Byte$hex(Byte_t byte, bool uppercase, bool prefix) {
struct Text_s text = {.tag=TEXT_ASCII};
text.ascii = GC_MALLOC_ATOMIC(8);
- if (prefix && uppercase)
- text.length = (int64_t)snprintf((char*)text.ascii, 8, "0x%02X", byte);
- else if (prefix && !uppercase)
- text.length = (int64_t)snprintf((char*)text.ascii, 8, "0x%02x", byte);
- else if (!prefix && uppercase)
- text.length = (int64_t)snprintf((char*)text.ascii, 8, "%02X", byte);
- else if (!prefix && !uppercase)
- text.length = (int64_t)snprintf((char*)text.ascii, 8, "%02x", byte);
+ char *p = (char*)text.ascii;
+ if (prefix) {
+ *(p++) = '0';
+ *(p++) = 'x';
+ }
+
+ if (uppercase) {
+ *(p++) = (byte/16) > 9 ? 'A' + (byte/16) - 10 : '0' + (byte/16);
+ *(p++) = (byte & 15) > 9 ? 'A' + (byte & 15) - 10 : '0' + (byte & 15);
+ } else {
+ *(p++) = (byte/16) > 9 ? 'a' + (byte/16) - 10 : '0' + (byte/16);
+ *(p++) = (byte & 15) > 9 ? 'a' + (byte & 15) - 10 : '0' + (byte & 15);
+ }
+ text.length = (int64_t)(p - text.ascii);
return text;
}
diff --git a/src/stdlib/c_strings.c b/src/stdlib/c_strings.c
index e74ccb68..c153a8a9 100644
--- a/src/stdlib/c_strings.c
+++ b/src/stdlib/c_strings.c
@@ -19,11 +19,6 @@ public Text_t CString$as_text(const void *c_string, bool colorize, const TypeInf
return Text$concat(colorize ? Text("\x1b[34mCString\x1b[m(") : Text("CString("), Text$quoted(text, colorize, Text("\"")), Text(")"));
}
-public Text_t CString$as_text_simple(const char *str)
-{
- return Text$format("%s", str);
-}
-
PUREFUNC public int32_t CString$compare(const void *x, const void *y, const TypeInfo_t *info)
{
(void)info;
diff --git a/src/stdlib/c_strings.h b/src/stdlib/c_strings.h
index 24cf99da..4df5c3ac 100644
--- a/src/stdlib/c_strings.h
+++ b/src/stdlib/c_strings.h
@@ -6,9 +6,9 @@
#include <stdint.h>
#include "types.h"
+#include "util.h"
Text_t CString$as_text(const char **str, bool colorize, const TypeInfo_t *info);
-Text_t CString$as_text_simple(const char *str);
PUREFUNC int CString$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool CString$equal(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC uint64_t CString$hash(const void *str, const TypeInfo_t *type);
diff --git a/src/stdlib/enums.c b/src/stdlib/enums.c
index 0c5cf196..404e3c50 100644
--- a/src/stdlib/enums.c
+++ b/src/stdlib/enums.c
@@ -74,8 +74,10 @@ public Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *typ
int32_t tag = *(int32_t*)obj;
NamedType_t value = type->EnumInfo.tags[tag-1];
- if (!value.type || value.type->size == 0)
- return Text$format(colorize ? "\x1b[1m%s\x1b[m" : "%s", value.name);
+ if (!value.type || value.type->size == 0) {
+ Text_t text = Text$from_str(value.name);
+ return colorize ? Texts(Text("\x1b[1m"), text, Text("\x1b[m")) : text;
+ }
ptrdiff_t byte_offset = sizeof(int32_t);
if (value.type->align && byte_offset % value.type->align > 0)
diff --git a/src/stdlib/files.c b/src/stdlib/files.c
index fa063697..900129f8 100644
--- a/src/stdlib/files.c
+++ b/src/stdlib/files.c
@@ -236,25 +236,27 @@ public int highlight_error(file_t *file, const char *start, const char *end, con
if (end < file->text || end > file->text + file->len)
start = end = file->text;
- const char *lineno_fmt, *normal_color, *empty_marker;
+ const char *lineno_prefix, *lineno_suffix, *normal_color, *empty_marker;
bool print_carets = false;
int printed = 0;
if (use_color) {
- lineno_fmt = "\x1b[0;2m%*lu\x1b(0\x78\x1b(B\x1b[m ";
+ lineno_prefix = "\x1b[0;2m";
+ lineno_suffix = "\x1b(0\x78\x1b(B\x1b[m ";
normal_color = "\x1b[m";
empty_marker = "\x1b(0\x61\x1b(B";
- printed += fprintf(stderr, "\x1b[33;4;1m%s\x1b[m\n", file->relative_filename);
+ printed += fprint(stderr, "\x1b[33;4;1m", file->relative_filename, "\x1b[m");
} else {
- lineno_fmt = "%*lu| ";
+ lineno_prefix = "";
+ lineno_suffix = "| ";
hl_color = "";
normal_color = "";
empty_marker = " ";
print_carets = true;
- printed += fprintf(stderr, "%s\n", file->relative_filename);
+ printed += fprint(stderr, file->relative_filename);
}
if (context_lines == 0)
- return fprintf(stderr, "%s%.*s%s", hl_color, (int)(end - start), start, normal_color);
+ return fprint(stderr, hl_color, string_slice(start, (size_t)(end - start)), normal_color);
int64_t start_line = get_line_number(file, start),
end_line = get_line_number(file, end);
@@ -271,14 +273,18 @@ public int highlight_error(file_t *file, const char *start, const char *end, con
for (int64_t line_no = first_line; line_no <= last_line; ++line_no) {
if (line_no > first_line + 5 && line_no < last_line - 5) {
if (use_color)
- printed += fprintf(stderr, "\x1b[0;2;3;4m ... %ld lines omitted ... \x1b[m\n", (last_line - first_line) - 11);
+ printed += fprint(stderr, "\x1b[0;2;3;4m ... ", (last_line - first_line) - 11, " lines omitted ... \x1b[m");
else
- printed += fprintf(stderr, " ... %ld lines omitted ...\n", (last_line - first_line) - 11);
+ printed += fprint(stderr, " ... ", (last_line - first_line) - 11, " lines omitted ...");
line_no = last_line - 6;
continue;
}
- printed += fprintf(stderr, lineno_fmt, digits, line_no);
+ int needed_spaces = digits;
+ for (int64_t n = line_no; n > 0; n /= 10)
+ needed_spaces -= 1;
+
+ printed += fprint_inline(stderr, lineno_prefix, repeated_char(' ', needed_spaces), line_no, lineno_suffix);
const char *line = get_line(file, line_no);
if (!line) break;
@@ -290,7 +296,7 @@ public int highlight_error(file_t *file, const char *start, const char *end, con
// Zero-width matches
if (p == start && start == end) {
- printed += fprintf(stderr, "%s%s%s", hl_color, empty_marker, normal_color);
+ printed += fprint_inline(stderr, hl_color, empty_marker, normal_color);
column += 1;
}
@@ -306,7 +312,7 @@ public int highlight_error(file_t *file, const char *start, const char *end, con
for (; *p && *p != '\r' && *p != '\n'; ++p)
printed += fputc_column(stderr, *p, *p, &column);
- printed += fprintf(stderr, "\n");
+ printed += fprint_inline(stderr, "\n");
const char *eol = line + strcspn(line, "\r\n");
if (print_carets && start >= line && start < eol && line <= start) {
diff --git a/src/stdlib/fpconv.c b/src/stdlib/fpconv.c
new file mode 100644
index 00000000..97699784
--- /dev/null
+++ b/src/stdlib/fpconv.c
@@ -0,0 +1,341 @@
+// This file defines a function to convert floating point numbers to strings.
+// For license, see: fpconv_license.txt
+#include <stdbool.h>
+#include <string.h>
+
+#include "fpconv.h"
+#include "powers.h"
+
+#define fracmask 0x000FFFFFFFFFFFFFU
+#define expmask 0x7FF0000000000000U
+#define hiddenbit 0x0010000000000000U
+#define signmask 0x8000000000000000U
+#define expbias (1023 + 52)
+
+#define absv(n) ((n) < 0 ? -(n) : (n))
+#define minv(a, b) ((a) < (b) ? (a) : (b))
+
+static uint64_t tens[] = {
+ 10000000000000000000U, 1000000000000000000U, 100000000000000000U,
+ 10000000000000000U, 1000000000000000U, 100000000000000U,
+ 10000000000000U, 1000000000000U, 100000000000U,
+ 10000000000U, 1000000000U, 100000000U,
+ 10000000U, 1000000U, 100000U,
+ 10000U, 1000U, 100U,
+ 10U, 1U
+};
+
+static inline uint64_t get_dbits(double d)
+{
+ union {
+ double dbl;
+ uint64_t i;
+ } dbl_bits = { d };
+
+ return dbl_bits.i;
+}
+
+static Fp build_fp(double d)
+{
+ uint64_t bits = get_dbits(d);
+
+ Fp fp;
+ fp.frac = bits & fracmask;
+ fp.exp = (bits & expmask) >> 52;
+
+ if (fp.exp) {
+ fp.frac += hiddenbit;
+ fp.exp -= expbias;
+
+ } else {
+ fp.exp = -expbias + 1;
+ }
+
+ return fp;
+}
+
+static void normalize(Fp* fp)
+{
+ while ((fp->frac & hiddenbit) == 0) {
+ fp->frac <<= 1;
+ fp->exp--;
+ }
+
+ int shift = 64 - 52 - 1;
+ fp->frac <<= shift;
+ fp->exp -= shift;
+}
+
+static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
+{
+ upper->frac = (fp->frac << 1) + 1;
+ upper->exp = fp->exp - 1;
+
+ while ((upper->frac & (hiddenbit << 1)) == 0) {
+ upper->frac <<= 1;
+ upper->exp--;
+ }
+
+ int u_shift = 64 - 52 - 2;
+
+ upper->frac <<= u_shift;
+ upper->exp = upper->exp - u_shift;
+
+
+ int l_shift = fp->frac == hiddenbit ? 2 : 1;
+
+ lower->frac = (fp->frac << l_shift) - 1;
+ lower->exp = fp->exp - l_shift;
+
+
+ lower->frac <<= lower->exp - upper->exp;
+ lower->exp = upper->exp;
+}
+
+static Fp multiply(Fp* a, Fp* b)
+{
+ const uint64_t lomask = 0x00000000FFFFFFFF;
+
+ uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
+ uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
+ uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
+ uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
+
+ uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32);
+ /* round up */
+ tmp += 1U << 31;
+
+ Fp fp = {
+ ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
+ a->exp + b->exp + 64
+ };
+
+ return fp;
+}
+
+static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
+{
+ while (rem < frac && delta - rem >= kappa &&
+ (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
+
+ digits[ndigits - 1]--;
+ rem += kappa;
+ }
+}
+
+static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
+{
+ uint64_t wfrac = upper->frac - fp->frac;
+ uint64_t delta = upper->frac - lower->frac;
+
+ Fp one;
+ one.frac = 1ULL << -upper->exp;
+ one.exp = upper->exp;
+
+ uint64_t part1 = upper->frac >> -one.exp;
+ uint64_t part2 = upper->frac & (one.frac - 1);
+
+ int idx = 0, kappa = 10;
+ uint64_t* divp;
+ /* 1000000000 */
+ for(divp = tens + 10; kappa > 0; divp++) {
+
+ uint64_t div = *divp;
+ unsigned digit = part1 / div;
+
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part1 -= digit * div;
+ kappa--;
+
+ uint64_t tmp = (part1 <<-one.exp) + part2;
+ if (tmp <= delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
+
+ return idx;
+ }
+ }
+
+ /* 10 */
+ uint64_t* unit = tens + 18;
+
+ while (true) {
+ part2 *= 10;
+ delta *= 10;
+ kappa--;
+
+ unsigned digit = part2 >> -one.exp;
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part2 &= one.frac - 1;
+ if (part2 < delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit);
+
+ return idx;
+ }
+
+ unit--;
+ }
+}
+
+static int grisu2(double d, char* digits, int* K)
+{
+ Fp w = build_fp(d);
+
+ Fp lower, upper;
+ get_normalized_boundaries(&w, &lower, &upper);
+
+ normalize(&w);
+
+ int k;
+ Fp cp = find_cachedpow10(upper.exp, &k);
+
+ w = multiply(&w, &cp);
+ upper = multiply(&upper, &cp);
+ lower = multiply(&lower, &cp);
+
+ lower.frac++;
+ upper.frac--;
+
+ *K = -k;
+
+ return generate_digits(&w, &upper, &lower, digits, K);
+}
+
+static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
+{
+ int exp = absv(K + ndigits - 1);
+
+ int max_trailing_zeros = 7;
+
+ if (neg) {
+ max_trailing_zeros -= 1;
+ }
+
+ /* write plain integer */
+ if (K >= 0 && (exp < (ndigits + max_trailing_zeros))) {
+
+ memcpy(dest, digits, (size_t)ndigits);
+ memset(dest + ndigits, '0', (size_t)K);
+
+ return ndigits + K;
+ }
+
+ /* write decimal w/o scientific notation */
+ if (K < 0 && (K > -7 || exp < 4)) {
+ int offset = ndigits - absv(K);
+ /* fp < 1.0 -> write leading zero */
+ if (offset <= 0) {
+ offset = -offset;
+ dest[0] = '0';
+ dest[1] = '.';
+ memset(dest + 2, '0', (size_t)offset);
+ memcpy(dest + offset + 2, digits, (size_t)ndigits);
+
+ return ndigits + 2 + offset;
+
+ /* fp > 1.0 */
+ } else {
+ memcpy(dest, digits, (size_t)offset);
+ dest[offset] = '.';
+ memcpy(dest + offset + 1, digits + offset, (size_t)(ndigits - offset));
+
+ return ndigits + 1;
+ }
+ }
+
+ /* write decimal w/ scientific notation */
+ ndigits = minv(ndigits, 18 - neg);
+
+ int idx = 0;
+ dest[idx++] = digits[0];
+
+ if (ndigits > 1) {
+ dest[idx++] = '.';
+ memcpy(dest + idx, digits + 1, (size_t)ndigits - 1);
+ idx += ndigits - 1;
+ }
+
+ dest[idx++] = 'e';
+
+ char sign = K + ndigits - 1 < 0 ? '-' : '+';
+ dest[idx++] = sign;
+
+ int cent = 0;
+
+ if (exp > 99) {
+ cent = exp / 100;
+ dest[idx++] = cent + '0';
+ exp -= cent * 100;
+ }
+ if (exp > 9) {
+ int dec = exp / 10;
+ dest[idx++] = dec + '0';
+ exp -= dec * 10;
+
+ } else if (cent) {
+ dest[idx++] = '0';
+ }
+
+ dest[idx++] = exp % 10 + '0';
+
+ return idx;
+}
+
+static int filter_special(double fp, char* dest)
+{
+ if (fp == 0.0) {
+ dest[0] = '0';
+ return 1;
+ }
+
+ uint64_t bits = get_dbits(fp);
+
+ bool nan = (bits & expmask) == expmask;
+
+ if (!nan) {
+ return 0;
+ }
+
+ if (bits & fracmask) {
+ dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
+
+ } else {
+ dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ }
+
+ return 3;
+}
+
+int fpconv_dtoa(double d, char dest[24])
+{
+ char digits[18];
+
+ int str_len = 0;
+ bool neg = false;
+
+ if (get_dbits(d) & signmask) {
+ dest[0] = '-';
+ str_len++;
+ neg = true;
+ }
+
+ int spec = filter_special(d, dest + str_len);
+
+ if (spec) {
+ return str_len + spec;
+ }
+
+ int K = 0;
+ int ndigits = grisu2(d, digits, &K);
+
+ str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
+
+ return str_len;
+}
diff --git a/src/stdlib/fpconv.h b/src/stdlib/fpconv.h
new file mode 100644
index 00000000..360c1f96
--- /dev/null
+++ b/src/stdlib/fpconv.h
@@ -0,0 +1,36 @@
+#ifndef FPCONV_H
+#define FPCONV_H
+
+// This file defines a function to convert floating point numbers to strings.
+// For license, see: fpconv_license.txt
+
+/* Fast and accurate double to string conversion based on Florian Loitsch's
+ * Grisu-algorithm[1].
+ *
+ * Input:
+ * fp -> the double to convert, dest -> destination buffer.
+ * The generated string will never be longer than 24 characters.
+ * Make sure to pass a pointer to at least 24 bytes of memory.
+ * The emitted string will not be null terminated.
+ *
+ * Output:
+ * The number of written characters.
+ *
+ * Exemplary usage:
+ *
+ * void print(double d)
+ * {
+ * char buf[24 + 1] // plus null terminator
+ * int str_len = fpconv_dtoa(d, buf);
+ *
+ * buf[str_len] = '\0';
+ * printf("%s", buf);
+ * }
+ *
+ */
+
+int fpconv_dtoa(double fp, char dest[24]);
+
+#endif
+
+/* [1] http://florian.loitsch.com/publications/dtoa-pldi2010.pdf */
diff --git a/src/stdlib/functiontype.c b/src/stdlib/functiontype.c
index f169057a..3769be2d 100644
--- a/src/stdlib/functiontype.c
+++ b/src/stdlib/functiontype.c
@@ -82,7 +82,7 @@ public Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type
OptionalText_t filename = get_function_filename(*(void**)fn);
int64_t line_num = get_function_line_num(*(void**)fn);
if (filename.length >= 0)
- text = Texts(text, Text(" ["), filename, Text$format(":%ld]", line_num));
+ text = Texts(text, Text(" ["), filename, Text(":"), Int64$as_text(&line_num, false, &Int64$info), Text("]"));
}
if (fn && colorize)
text = Text$concat(Text("\x1b[32;1m"), text, Text("\x1b[m"));
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index bb39d99c..86cdeb56 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -9,26 +9,44 @@
#include <stdio.h>
#include <stdlib.h>
-#include "lists.h"
#include "datatypes.h"
#include "integers.h"
+#include "lists.h"
#include "optionals.h"
+#include "print.h"
#include "siphash.h"
#include "text.h"
#include "types.h"
public int Int$print(FILE *f, Int_t i) {
if (likely(i.small & 1L)) {
- return fprintf(f, "%ld", (i.small)>>2L);
+ return _print_int(f, (int64_t)((i.small)>>2L));
} else {
- char *str = mpz_get_str(NULL, 10, *i.big);
- return fputs(str, f);
+ return gmp_fprintf(f, "%Zd", *i.big);
}
}
+static inline Text_t _int64_to_text(int64_t n)
+{
+ char buf[21] = {[20]=0}; // Big enough for INT64_MIN + '\0'
+ char *p = &buf[19];
+ bool negative = n < 0;
+
+ if (n == 0)
+ *(p--) = '0';
+
+ for (; n > 0; n /= 10)
+ *(p--) = '0' + (n % 10);
+
+ if (negative)
+ *(p--) = '-';
+
+ return Text$from_strn(p + 1, (size_t)(&buf[19] - p));
+}
+
public Text_t Int$value_as_text(Int_t i) {
if (likely(i.small & 1L)) {
- return Text$format("%ld", i.small>>2L);
+ return _int64_to_text(i.small >> 2L);
} else {
char *str = mpz_get_str(NULL, 10, *i.big);
return Text$from_str(str);
@@ -96,40 +114,20 @@ public PUREFUNC uint64_t Int$hash(const void *vx, const TypeInfo_t *info) {
}
}
-public Text_t Int$format(Int_t i, Int_t digits_int) {
- int64_t digits = Int64$from_int(digits_int, false);
- if (likely(i.small & 1L)) {
- return Text$format("%0.*ld", digits, (int64_t)((i.small)>>2L));
- } else {
- char *str = mpz_get_str(NULL, 10, *i.big);
- bool negative = (str[0] == '-');
- int64_t needed_zeroes = digits - (int64_t)strlen(str);
- if (needed_zeroes <= 0)
- return Text$from_str(str);
-
- char *zeroes = GC_MALLOC_ATOMIC((size_t)(needed_zeroes));
- memset(zeroes, '0', (size_t)(needed_zeroes));
- if (negative)
- return Text$concat(Text("-"), Text$from_str(zeroes), Text$from_str(str + 1));
- else
- return Text$concat(Text$from_str(zeroes), Text$from_str(str));
- }
-}
-
public Text_t Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
if (Int$is_negative(i))
return Text$concat(Text("-"), Int$hex(Int$negative(i), digits_int, uppercase, prefix));
- int64_t digits = Int64$from_int(digits_int, false);
if (likely(i.small & 1L)) {
- const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx");
- return Text$format(hex_fmt, digits, (i.small)>>2L);
+ uint64_t u64 = (uint64_t)(i.small >> 2);
+ return Text$from_str(String(hex(u64, .no_prefix=!prefix, .digits=Int32$from_int(digits_int, false), .uppercase=uppercase)));
} else {
char *str = mpz_get_str(NULL, 16, *i.big);
if (uppercase) {
for (char *c = str; *c; c++)
*c = (char)toupper(*c);
}
+ int64_t digits = Int64$from_int(digits_int, false);
int64_t needed_zeroes = digits - (int64_t)strlen(str);
if (needed_zeroes <= 0)
return prefix ? Text$concat(Text("0x"), Text$from_str(str)) : Text$from_str(str);
@@ -147,11 +145,11 @@ public Text_t Int$octal(Int_t i, Int_t digits_int, bool prefix) {
if (Int$is_negative(i))
return Text$concat(Text("-"), Int$octal(Int$negative(i), digits_int, prefix));
- int64_t digits = Int64$from_int(digits_int, false);
if (likely(i.small & 1L)) {
- const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo";
- return Text$format(octal_fmt, digits, (i.small)>>2L);
+ uint64_t u64 = (uint64_t)(i.small >> 2);
+ return Text$from_str(String(oct(u64, .no_prefix=!prefix, .digits=Int32$from_int(digits_int, false))));
} else {
+ int64_t digits = Int64$from_int(digits_int, false);
char *str = mpz_get_str(NULL, 8, *i.big);
int64_t needed_zeroes = digits - (int64_t)strlen(str);
if (needed_zeroes <= 0)
@@ -581,11 +579,12 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
#define __builtin_add_overflow(x, y, result) ({ *(result) = (x) + (y); false; })
#endif
-#define DEFINE_INT_TYPE(c_type, KindOfInt, fmt, min_val, max_val, to_attr)\
+#define DEFINE_INT_TYPE(c_type, KindOfInt, min_val, max_val, to_attr)\
public Text_t KindOfInt ## $as_text(const void *i, bool colorize, const TypeInfo_t *info) { \
(void)info; \
if (!i) return Text(#KindOfInt); \
- return Text$format(colorize ? "\x1b[35m" fmt "\x1b[m" : fmt, *(c_type*)i); \
+ Text_t text = _int64_to_text((int64_t)(*(c_type*)i)); \
+ return colorize ? Texts(Text("\033[35m"), text, Text("\033[m")) : text; \
} \
public PUREFUNC int32_t KindOfInt ## $compare(const void *x, const void *y, const TypeInfo_t *info) { \
(void)info; \
@@ -601,9 +600,6 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
public CONSTFUNC c_type KindOfInt ## $clamped(c_type x, c_type min, c_type max) { \
return x < min ? min : (x > max ? max : x); \
} \
- public Text_t KindOfInt ## $format(c_type i, Int_t digits_int) { \
- return Text$format("%0*ld", Int32$from_int(digits_int, false), (int64_t)i); \
- } \
public Text_t KindOfInt ## $hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \
Int_t as_int = Int$from_int64((int64_t)i); \
return Int$hex(as_int, digits_int, uppercase, prefix); \
@@ -685,10 +681,10 @@ public void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const Ty
}, \
};
-DEFINE_INT_TYPE(int64_t, Int64, "%ld", INT64_MIN, INT64_MAX, __attribute__(()))
-DEFINE_INT_TYPE(int32_t, Int32, "%d", INT32_MIN, INT32_MAX, CONSTFUNC)
-DEFINE_INT_TYPE(int16_t, Int16, "%d", INT16_MIN, INT16_MAX, CONSTFUNC)
-DEFINE_INT_TYPE(int8_t, Int8, "%d", INT8_MIN, INT8_MAX, CONSTFUNC)
+DEFINE_INT_TYPE(int64_t, Int64, INT64_MIN, INT64_MAX, __attribute__(()))
+DEFINE_INT_TYPE(int32_t, Int32, INT32_MIN, INT32_MAX, CONSTFUNC)
+DEFINE_INT_TYPE(int16_t, Int16, INT16_MIN, INT16_MAX, CONSTFUNC)
+DEFINE_INT_TYPE(int8_t, Int8, INT8_MIN, INT8_MAX, CONSTFUNC)
#undef DEFINE_INT_TYPE
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h
index 7b7cf12e..4eaac916 100644
--- a/src/stdlib/integers.h
+++ b/src/stdlib/integers.h
@@ -26,7 +26,6 @@
Text_t type_name ## $as_text(const void *i, bool colorize, const TypeInfo_t *type); \
PUREFUNC int32_t type_name ## $compare(const void *x, const void *y, const TypeInfo_t *type); \
PUREFUNC bool type_name ## $equal(const void *x, const void *y, const TypeInfo_t *type); \
- Text_t type_name ## $format(c_type i, Int_t digits); \
Text_t type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \
Text_t type_name ## $octal(c_type i, Int_t digits, bool prefix); \
List_t type_name ## $bits(c_type x); \
@@ -96,7 +95,6 @@ CONSTFUNC bool Int$is_between(const Int_t x, const Int_t low, const Int_t high);
CONSTFUNC Int_t Int$clamped(Int_t x, Int_t low, Int_t high);
PUREFUNC bool Int$equal(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Int$equal_value(const Int_t x, const Int_t y);
-Text_t Int$format(Int_t i, Int_t digits);
Text_t Int$hex(Int_t i, Int_t digits, bool uppercase, bool prefix);
Text_t Int$octal(Int_t i, Int_t digits, bool prefix);
PUREFUNC Closure_t Int$to(Int_t first, Int_t last, OptionalInt_t step);
diff --git a/src/stdlib/memory.c b/src/stdlib/memory.c
index ed2ded40..46729f83 100644
--- a/src/stdlib/memory.c
+++ b/src/stdlib/memory.c
@@ -16,7 +16,8 @@
public Text_t Memory$as_text(const void *p, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!p) return Text("Memory");
- return Text$format(colorize ? "\x1b[0;34;1mMemory<%p>\x1b[m" : "Memory<%p>", p);
+ Text_t text = Text$from_str(String("Memory<", *(void**)p, ">"));
+ return colorize ? Texts(Text("\x1b[0;34;1m"), text, Text("\x1b[m")) : text;
}
public const TypeInfo_t Memory$info = {
diff --git a/src/stdlib/metamethods.c b/src/stdlib/metamethods.c
index a7c9424b..ab7bb26e 100644
--- a/src/stdlib/metamethods.c
+++ b/src/stdlib/metamethods.c
@@ -104,7 +104,7 @@ public void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *ty
public int generic_print(const void *obj, bool colorize, const TypeInfo_t *type)
{
Text_t text = generic_as_text(obj, colorize, type);
- return Text$print(stdout, text) + printf("\n");
+ return Text$print(stdout, text) + fputc('\n', stdout);
}
__attribute__((noreturn))
diff --git a/src/stdlib/nums.c b/src/stdlib/nums.c
index c488b551..3213fd2f 100644
--- a/src/stdlib/nums.c
+++ b/src/stdlib/nums.c
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include "fpconv.h"
#include "lists.h"
#include "nums.h"
#include "string.h"
@@ -16,7 +17,11 @@
public PUREFUNC Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!f) return Text("Num");
- return Text$format(colorize ? "\x1b[35m%.16g\x1b[33;2m\x1b[m" : "%.16g", *(double*)f);
+ char *str = GC_MALLOC_ATOMIC(24);
+ int len = fpconv_dtoa(*(double*)f, str);
+ static const Text_t color_prefix = Text("\x1b[35m"), color_suffix = Text("\x1b[m");
+ Text_t text = Text$from_strn(str, (size_t)len);
+ return colorize ? Texts(color_prefix, text, color_suffix) : text;
}
public PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *info) {
@@ -52,16 +57,23 @@ public CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute
return (diff < epsilon);
}
-public Text_t Num$format(double f, Int_t precision) {
- return Text$format("%.*f", (int)Int64$from_int(precision, false), f);
+public Text_t Num$percent(double f, double precision) {
+ double d = 100. * f;
+ d = Num$with_precision(d, precision);
+ return Texts(Num$as_text(&d, false, &Num$info), Text("%"));
}
-public Text_t Num$scientific(double f, Int_t precision) {
- return Text$format("%.*e", (int)Int64$from_int(precision, false), f);
-}
-
-public Text_t Num$percent(double f, Int_t precision) {
- return Text$format("%.*f%%", (int)Int64$from_int(precision, false), 100.*f);
+public CONSTFUNC double Num$with_precision(double num, double precision) {
+ if (precision == 0.0) return num;
+ // Precision will be, e.g. 0.01 or 100.
+ if (precision < 1.) {
+ double inv = round(1./precision); // Necessary to make the math work
+ double k = num * inv;
+ return round(k) / inv;
+ } else {
+ double k = num / precision;
+ return round(k) * precision;
+ }
}
public CONSTFUNC double Num$mod(double num, double modulus) {
@@ -120,7 +132,8 @@ public const TypeInfo_t Num$info = {
public PUREFUNC Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *info) {
(void)info;
if (!f) return Text("Num32");
- return Text$format(colorize ? "\x1b[35m%.8g\x1b[33;2m\x1b[m" : "%.8g", (double)*(float*)f);
+ double d = (double)(*(float*)f);
+ return Num$as_text(&d, colorize, &Num$info);
}
public PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *info) {
@@ -148,16 +161,23 @@ public CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute)
return (diff < epsilon);
}
-public Text_t Num32$format(float f, Int_t precision) {
- return Text$format("%.*f", (int)Int64$from_int(precision, false), (double)f);
-}
-
-public Text_t Num32$scientific(float f, Int_t precision) {
- return Text$format("%.*e", (int)Int64$from_int(precision, false), (double)f);
+public Text_t Num32$percent(float f, float precision) {
+ double d = 100. * (double)f;
+ d = Num$with_precision(d, (double)precision);
+ return Texts(Num$as_text(&d, false, &Num$info), Text("%"));
}
-public Text_t Num32$percent(float f, Int_t precision) {
- return Text$format("%.*f%%", (int)Int64$from_int(precision, false), 100.*(double)f);
+public CONSTFUNC float Num32$with_precision(float num, float precision) {
+ if (precision == 0.0f) return num;
+ // Precision will be, e.g. 0.01 or 100.
+ if (precision < 1.f) {
+ float inv = roundf(1.f/precision); // Necessary to make the math work
+ float k = num * inv;
+ return roundf(k) / inv;
+ } else {
+ float k = num / precision;
+ return roundf(k) * precision;
+ }
}
public CONSTFUNC float Num32$mod(float num, float modulus) {
diff --git a/src/stdlib/nums.h b/src/stdlib/nums.h
index 5871c904..fdd9e227 100644
--- a/src/stdlib/nums.h
+++ b/src/stdlib/nums.h
@@ -21,9 +21,8 @@ Text_t Num$as_text(const void *f, bool colorize, const TypeInfo_t *type);
PUREFUNC int32_t Num$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Num$equal(const void *x, const void *y, const TypeInfo_t *type);
CONSTFUNC bool Num$near(double a, double b, double ratio, double absolute);
-Text_t Num$format(double f, Int_t precision);
-Text_t Num$scientific(double f, Int_t precision);
-Text_t Num$percent(double f, Int_t precision);
+Text_t Num$percent(double f, double precision);
+double CONSTFUNC Num$with_precision(double num, double precision);
double Num$mod(double num, double modulus);
double Num$mod1(double num, double modulus);
CONSTFUNC bool Num$isinf(double n);
@@ -76,9 +75,8 @@ Text_t Num32$as_text(const void *f, bool colorize, const TypeInfo_t *type);
PUREFUNC int32_t Num32$compare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Num32$equal(const void *x, const void *y, const TypeInfo_t *type);
CONSTFUNC bool Num32$near(float a, float b, float ratio, float absolute);
-Text_t Num32$format(float f, Int_t precision);
-Text_t Num32$scientific(float f, Int_t precision);
-Text_t Num32$percent(float f, Int_t precision);
+Text_t Num32$percent(float f, float precision);
+float CONSTFUNC Num32$with_precision(float num, float precision);
float Num32$mod(float num, float modulus);
float Num32$mod1(float num, float modulus);
CONSTFUNC bool Num32$isinf(float n);
diff --git a/src/stdlib/pointers.c b/src/stdlib/pointers.c
index d766a9b3..6874dd3c 100644
--- a/src/stdlib/pointers.c
+++ b/src/stdlib/pointers.c
@@ -41,12 +41,15 @@ public Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *ty
if (top_level) {
root = ptr;
} else if (ptr == root) {
- return Text$format(colorize ? "\x1b[34;1m%s~1\x1b[m" : "%s~1", ptr_info.sigil);
+ Text_t text = Texts(Text$from_str(ptr_info.sigil), Text("~1"));
+ return colorize ? Texts(Text("\x1b[34;1m"), text, Text("\x1b[m")) : text;
} else {
TypeInfo_t rec_table = *Table$info(type, &Int64$info);
int64_t *id = Table$get(pending, x, &rec_table);
- if (id)
- return Text$format(colorize ? "\x1b[34;1m%s~%ld\x1b[m" : "%s~%ld", ptr_info.sigil, *id);
+ if (id) {
+ Text_t text = Texts(Text$from_str(ptr_info.sigil), Int64$as_text(id, false, &Int64$info));
+ return colorize ? Texts(Text("\x1b[34;1m"), text, Text("\x1b[m")) : text;
+ }
int64_t next_id = pending.entries.length + 2;
Table$set(&pending, x, &next_id, &rec_table);
}
diff --git a/src/stdlib/powers.h b/src/stdlib/powers.h
new file mode 100644
index 00000000..d1829b60
--- /dev/null
+++ b/src/stdlib/powers.h
@@ -0,0 +1,91 @@
+// This file defines a function to get power-of-10 information about a floating
+// point number, used in fpconv.c
+// For license, see: fpconv_license.txt
+
+#include <stdint.h>
+
+#define npowers 87
+#define steppowers 8
+#define firstpower -348 /* 10 ^ -348 */
+
+#define expmax -32
+#define expmin -60
+
+
+typedef struct Fp {
+ uint64_t frac;
+ int exp;
+} Fp;
+
+static const Fp powers_ten[] = {
+ { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 },
+ { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 },
+ { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 },
+ { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 },
+ { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 },
+ { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 },
+ { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 },
+ { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 },
+ { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 },
+ { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 },
+ { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 },
+ { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 },
+ { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 },
+ { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 },
+ { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 },
+ { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 },
+ { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 },
+ { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 },
+ { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 },
+ { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 },
+ { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 },
+ { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 },
+ { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 },
+ { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 },
+ { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 },
+ { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 },
+ { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 },
+ { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 },
+ { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 },
+ { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 },
+ { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 },
+ { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 },
+ { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 },
+ { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 },
+ { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 },
+ { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 },
+ { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 },
+ { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 },
+ { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 },
+ { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 },
+ { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 },
+ { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 },
+ { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 },
+ { 12648080533535911531U, 1066 }
+};
+
+static Fp find_cachedpow10(int exp, int* k)
+{
+ const double one_log_ten = 0.30102999566398114;
+
+ int approx = -(exp + npowers) * one_log_ten;
+ int idx = (approx - firstpower) / steppowers;
+
+ while (1) {
+ int current = exp + powers_ten[idx].exp + 64;
+
+ if (current < expmin) {
+ idx++;
+ continue;
+ }
+
+ if (current > expmax) {
+ idx--;
+ continue;
+ }
+
+ *k = (firstpower + idx * steppowers);
+
+ return powers_ten[idx];
+ }
+}
diff --git a/src/stdlib/print.c b/src/stdlib/print.c
index aeb71fae..df10a54f 100644
--- a/src/stdlib/print.c
+++ b/src/stdlib/print.c
@@ -1,16 +1,103 @@
// This file defines some of the helper functions used for printing values
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "fpconv.h"
#include "print.h"
#include "util.h"
-#include <stdio.h>
+public int _print_int(FILE *f, int64_t n)
+{
+ char buf[21] = {[20]=0}; // Big enough for INT64_MIN + '\0'
+ char *p = &buf[19];
+ bool negative = n < 0;
+
+ if (n == 0)
+ *(p--) = '0';
+
+ for (; n > 0; n /= 10)
+ *(p--) = '0' + (n % 10);
+
+ if (negative)
+ *(p--) = '-';
+
+ return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
+}
+
+public int _print_uint(FILE *f, uint64_t n)
+{
+ char buf[21] = {[20]=0}; // Big enough for UINT64_MAX + '\0'
+ char *p = &buf[19];
+
+ if (n == 0)
+ *(p--) = '0';
+
+ for (; n > 0; n /= 10)
+ *(p--) = '0' + (n % 10);
+
+ return fwrite(p + 1, sizeof(char), (size_t)(&buf[19] - p), f);
+}
+
+public int _print_hex(FILE *f, hex_format_t hex)
+{
+ int printed = 0;
+ if (!hex.no_prefix) printed += fputs("0x", f);
+ if (hex.digits > 0) {
+ for (uint64_t n = hex.n; n > 0 && hex.digits > 0; n /= 16) {
+ hex.digits -= 1;
+ }
+ for (; hex.digits > 0; hex.digits -= 1) {
+ printed += fputc('0', f);
+ }
+ }
+ char buf[9] = {[8]='\0'}; // Enough space for FFFFFFFF + '\0'
+ char *p = &buf[7];
+ for (uint64_t n = hex.n; n > 0; n /= 16) {
+ uint8_t digit = n % 16;
+ if (digit <= 9)
+ *(p--) = '0' + digit;
+ else if (hex.uppercase)
+ *(p--) = 'A' + digit - 10;
+ else
+ *(p--) = 'a' + digit - 10;
+ }
+ printed += (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[7] - p), f);
+ return printed;
+}
+
+public int _print_oct(FILE *f, oct_format_t oct)
+{
+ int printed = 0;
+ if (!oct.no_prefix) printed += fputs("0o", f);
+ if (oct.digits > 0) {
+ for (uint64_t n = oct.n; n > 0 && oct.digits > 0; n /= 8) {
+ oct.digits -= 1;
+ }
+ for (; oct.digits > 0; oct.digits -= 1) {
+ printed += fputc('0', f);
+ }
+ }
+ char buf[12] = {[11]='\0'}; // Enough space for octal UINT64_MAX + '\0'
+ char *p = &buf[10];
+ for (uint64_t n = oct.n; n > 0; n /= 8) {
+ *(p--) = '0' + (n % 8);
+ }
+ printed += (int)fwrite(p + 1, sizeof(char), (size_t)(&buf[10] - p), f);
+ return printed;
+}
+
+public int _print_double(FILE *f, double n)
+{
+ static char buf[24];
+ int len = fpconv_dtoa(n, buf);
+ return (int)fwrite(buf, sizeof(char), (size_t)len, f);
+}
public int _print_char(FILE *f, char c)
{
-#if PRINT_COLOR
-#define ESC(e) "\033[35m'\033[34;1m\\" e "\033[0;35m'\033[m"
-#else
#define ESC(e) "'\\" e "'"
-#endif
const char *named[256] = {['\'']=ESC("'"), ['\\']=ESC("\\"),
['\n']=ESC("n"), ['\t']=ESC("t"), ['\r']=ESC("r"),
['\033']=ESC("e"), ['\v']=ESC("v"), ['\a']=ESC("a"), ['\b']=ESC("b")};
@@ -18,32 +105,20 @@ public int _print_char(FILE *f, char c)
if (name != NULL)
return fputs(name, f);
else if (isprint(c))
-#if PRINT_COLOR
- return fprintf(f, "\033[35m'%c'\033[m"), c);
-#else
- return fprintf(f, "'%c'", c);
-#endif
+ return fputc('\'', f) + fputc(c, f) + fputc('\'', f);
else
- return fprintf(f, ESC("x%02X"), (uint8_t)c);
+ return (fputs("'\\x", f) + _print_hex(f, hex((uint64_t)c, .digits=2, .no_prefix=true, .uppercase=true))
+ + fputs("'", f));
#undef ESC
}
public int _print_quoted(FILE *f, quoted_t quoted)
{
-#if PRINT_COLOR
-#define ESC(e) "\033[34;1m\\" e "\033[0;35m"
-#else
#define ESC(e) "\\" e
-#endif
const char *named[256] = {['"']=ESC("\""), ['\\']=ESC("\\"),
['\n']=ESC("n"), ['\t']=ESC("t"), ['\r']=ESC("r"),
['\033']=ESC("e"), ['\v']=ESC("v"), ['\a']=ESC("a"), ['\b']=ESC("b")};
- int printed =
-#if PRINT_COLOR
- fputs("\033[35m\"", f);
-#else
- fputc('"', f);
-#endif
+ int printed = fputc('"', f);
for (const char *p = quoted.str; *p; p++) {
const char *name = named[(uint8_t)*p];
if (name != NULL) {
@@ -51,14 +126,10 @@ public int _print_quoted(FILE *f, quoted_t quoted)
} else if (isprint(*p) || (uint8_t)*p > 0x7F) {
printed += fputc(*p, f);
} else {
- printed += fprintf(f, ESC("x%02X"), (uint8_t)*p);
+ printed += fputs("\\x", f) + _print_hex(f, hex((uint64_t)*p, .digits=2, .no_prefix=true, .uppercase=true));
}
}
-#if PRINT_COLOR
- printed += fputs("\"\033[m", f);
-#else
printed += fputc('"', f);
-#endif
#undef ESC
return printed;
}
diff --git a/src/stdlib/print.h b/src/stdlib/print.h
index 243826e0..454ef6b8 100644
--- a/src/stdlib/print.h
+++ b/src/stdlib/print.h
@@ -8,8 +8,6 @@
// print_err(...) - print an error message and exit with EXIT_FAILURE
// String(...) - return an allocated string
//
-// If you put `#define PRINT_COLOR 1` before the import, text will be printed
-// with terminal colors.
#include <assert.h>
#include <ctype.h>
@@ -26,10 +24,6 @@
#include "datatypes.h"
#include "mapmacro.h"
-#ifndef PRINT_COLOR
-#define PRINT_COLOR 0
-#endif
-
// GCC lets you define macro-like functions which are always inlined and never
// compiled using this combination of flags. See: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
#ifndef PRINT_FN
@@ -56,12 +50,6 @@ typedef struct {
#define oct(x, ...) ((oct_format_t){.n=x, __VA_ARGS__})
typedef struct {
- double n;
- int precision;
-} num_format_t;
-#define num_fmt(x, ...) ((num_format_t){.n=x, __VA_ARGS__})
-
-typedef struct {
const char *str;
} quoted_t;
#define quoted(s) ((quoted_t){s})
@@ -72,37 +60,36 @@ typedef struct {
} string_slice_t;
#define string_slice(...) ((string_slice_t){__VA_ARGS__})
+typedef struct {
+ char c;
+ int length;
+} repeated_char_t;
+#define repeated_char(ch, len) ((repeated_char_t){.c=ch, .length=len})
+
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define FMT64 "ll"
#else
#define FMT64 "l"
#endif
-#if PRINT_COLOR
-#define hl(s) "\033[35m" s "\033[m"
-#else
-#define hl(s) s
-#endif
-PRINT_FN _print_int(FILE *f, int64_t x) { return fprintf(f, hl("%"FMT64"d"), x); }
-PRINT_FN _print_uint(FILE *f, uint64_t x) { return fprintf(f, hl("%"FMT64"u"), x); }
-PRINT_FN _print_float(FILE *f, float x) { return fprintf(f, hl("%g"), (double)x); }
-PRINT_FN _print_double(FILE *f, double x) { return fprintf(f, hl("%g"), x); }
-PRINT_FN _print_pointer(FILE *f, void *p) { return fprintf(f, hl("%p"), p); }
-PRINT_FN _print_bool(FILE *f, bool b) { return fputs(b ? hl("yes") : hl("no"), f); }
+int _print_int(FILE *f, int64_t x);
+int _print_uint(FILE *f, uint64_t x);
+int _print_double(FILE *f, double x);
+int _print_hex(FILE *f, hex_format_t hex);
+int _print_oct(FILE *f, oct_format_t oct);
+PRINT_FN _print_float(FILE *f, float x) { return _print_double(f, (double)x); }
+PRINT_FN _print_pointer(FILE *f, void *p) { return _print_hex(f, hex((uint64_t)p)); }
+PRINT_FN _print_bool(FILE *f, bool b) { return fputs(b ? "yes" : "no", f); }
PRINT_FN _print_str(FILE *f, const char *s) { return fputs(s ? s : "(null)", f); }
int _print_char(FILE *f, char c);
int _print_quoted(FILE *f, quoted_t quoted);
PRINT_FN _print_string_slice(FILE *f, string_slice_t slice) { return slice.str ? fwrite(slice.str, 1, slice.length, f) : (size_t)fputs("(null)", f); }
-PRINT_FN _print_hex(FILE *f, hex_format_t hex) {
- return fprintf(f, hex.no_prefix ? (hex.uppercase ? hl("%0*"FMT64"X") : hl("%0*"FMT64"x")) : (hex.uppercase ? hl("0x%0*"FMT64"X") : hl("%#0*"FMT64"x")), hex.digits, hex.n);
-}
-PRINT_FN _print_oct(FILE *f, oct_format_t oct) {
- return fprintf(f, oct.no_prefix ? hl("%0*"FMT64"o") : hl("%#0*"FMT64"o"), oct.digits, oct.n);
-}
-PRINT_FN _print_num_format(FILE *f, num_format_t num) {
- return fprintf(f, hl("%.*lf"), num.precision, num.n);
+PRINT_FN _print_repeated_char(FILE *f, repeated_char_t repeated) {
+ int len = 0;
+ for (int n = 0; n < repeated.length; n++)
+ len += fputc(repeated.c, f);
+ return len;
}
-#undef hl
extern int Text$print(FILE *stream, Text_t text);
extern int Path$print(FILE *stream, Path_t path);
@@ -125,9 +112,9 @@ extern int Int$print(FILE *f, Int_t i);
double: _print_double, \
hex_format_t: _print_hex, \
oct_format_t: _print_oct, \
- num_format_t: _print_num_format, \
quoted_t: _print_quoted, \
string_slice_t: _print_string_slice, \
+ repeated_char_t: _print_repeated_char, \
Text_t: Text$print, \
Path_t: Path$print, \
Int_t: Int$print, \
diff --git a/src/stdlib/stacktrace.c b/src/stdlib/stacktrace.c
index 798da218..d460ba58 100644
--- a/src/stdlib/stacktrace.c
+++ b/src/stdlib/stacktrace.c
@@ -32,10 +32,21 @@ static void fprint_context(FILE *out, const char *filename, int lineno, int cont
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = '\0';
- if (cur_line >= lineno - context_before)
- fprintf(out, USE_COLOR ? "%s\033[2m%*d\033(0\x78\x1b(B%s%s\033[m\n" : "%s%*d| %s%s\n",
- cur_line == lineno ? (USE_COLOR ? "\033[31;1m>\033[m " : "> ") : " ",
- num_width, cur_line, USE_COLOR ? (cur_line == lineno ? "\033[0;31;1m" : "\033[0m") : "", line);
+ if (cur_line >= lineno - context_before) {
+ int w = 1;
+ for (int n = cur_line; n >= 10; n /= 10) w += 1;
+
+ if (USE_COLOR) {
+ fprint(out, cur_line == lineno ? "\033[31;1m>\033[m " : " ", "\033[2m",
+ repeated_char(' ', num_width-w),
+ cur_line, "\033(0\x78\033(B", cur_line == lineno ? "\033[0;31;1m" : "\033[0m",
+ line, "\033[m");
+ } else {
+ fprint(out, cur_line == lineno ? "> " : " ",
+ repeated_char(' ', num_width-w),
+ cur_line, "| ", line);
+ }
+ }
cur_line += 1;
if (cur_line > lineno + context_after)
@@ -69,15 +80,14 @@ static void _print_stack_frame(FILE *out, const char *cwd, const char *install_d
if (strncmp(filename, cwd, strlen(cwd)) == 0)
filename += strlen(cwd);
- fprintf(out, USE_COLOR ? "\033[1mIn \033[33m%s()\033[37m" : "In %s()", function_display);
+ fprint_inline(out, USE_COLOR ? "\033[1mIn \033[33m" : "In ", function_display, USE_COLOR ? "()\033[37m" : "()");
if (filename) {
if (install_dir[0] && strncmp(filename, install_dir, strlen(install_dir)) == 0)
- fprintf(out, USE_COLOR ? " in library \033[35m%s:%d" : " in library %s:%d",
- filename, lineno);
+ fprint_inline(out, USE_COLOR ? " in library \033[35m" : " in library ", filename, ":", lineno);
else
- fprintf(out, USE_COLOR ? " in \033[35m%s:%d" : " in %s:%d", filename, lineno);
+ fprint(out, USE_COLOR ? " in \033[35m" : " in ", filename, ":", lineno);
}
- fprintf(out, USE_COLOR ? "\033[m\n" : "\n");
+ fprint(out, USE_COLOR ? "\033[m" : "");
if (filename)
fprint_context(out, filename, lineno, 3, 1);
} else {
diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c
index 7ee249ab..71257b8e 100644
--- a/src/stdlib/stdlib.c
+++ b/src/stdlib/stdlib.c
@@ -465,26 +465,33 @@ public void start_inspect(const char *filename, int64_t start, int64_t end)
file = load_file(filename);
if (file) {
- const char *spaces = " ";
- int64_t first_line_len = (int64_t)strcspn(file->text + start, "\r\n");
+ size_t first_line_len = strcspn(file->text + start, "\r\n");
const char *slash = strrchr(filename, '/');
const char *file_base = slash ? slash + 1 : filename;
int64_t line_num = get_line_number(file, file->text + start);
- fprintf(stdout, USE_COLOR ? "%.*s\x1b[33;1m>> \x1b[m%.*s %.*s\x1b[32;2m[%s:%ld]\x1b[m\n" : "%.*s>> %.*s %.*s[%s:%ld]\n",
- 3*_inspect_depth, spaces, first_line_len, file->text + start,
- MAX(0, 35-first_line_len-3*_inspect_depth), spaces, file_base, line_num);
+ if (USE_COLOR) {
+ print(repeated_char(' ', 3*_inspect_depth), "\x1b[33;1m>> \x1b[m",
+ string_slice(file->text + start, first_line_len),
+ " ", repeated_char(' ', MAX(0, 35-(int64_t)first_line_len-3*_inspect_depth)),
+ "\x1b[32;2m[", file_base, ":", line_num, "]\x1b[m");
+ } else {
+ print(repeated_char(' ', 3*_inspect_depth), ">> ",
+ string_slice(file->text + start, first_line_len),
+ " ", repeated_char(' ', MAX(0, 35-(int64_t)first_line_len-3*_inspect_depth)),
+ "[", file_base, ":", line_num, "]");
+ }
// For multi-line expressions, dedent each and print it on a new line with ".. " in front:
- if (end > start + first_line_len) {
+ if (end > start + (int64_t)first_line_len) {
const char *line_start = get_line(file, line_num);
int64_t indent_len = (int64_t)strspn(line_start, " \t");
for (const char *line = file->text + start + first_line_len; line < file->text + end; line += strcspn(line, "\r\n")) {
line += strspn(line, "\r\n");
if ((int64_t)strspn(line, " \t") >= indent_len)
line += indent_len;
- fprintf(stdout, USE_COLOR ? "%.*s\x1b[33m.. \x1b[m%.*s\n" : "%.*s.. %.*s\n",
- 3*_inspect_depth, spaces, strcspn(line, "\r\n"), line);
+ print(repeated_char(' ', 3*_inspect_depth), USE_COLOR ? "\x1b[33m.. " : ".. ",
+ string_slice(line, strcspn(line, "\r\n")));
}
}
}
diff --git a/src/stdlib/structs.c b/src/stdlib/structs.c
index 9a14779e..d4a22d93 100644
--- a/src/stdlib/structs.c
+++ b/src/stdlib/structs.c
@@ -143,10 +143,12 @@ PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const Type
{
if (!obj) return Text$from_str(type->StructInfo.name);
- if (type->StructInfo.is_secret || type->StructInfo.is_opaque)
- return Text$format(colorize ? "\x1b[0;1m%s\x1b[m(...)" : "%s(...)", type->StructInfo.name);
+ Text_t name = Text$from_str(type->StructInfo.name);
+ if (type->StructInfo.is_secret || type->StructInfo.is_opaque) {
+ return colorize ? Texts(Text("\x1b[0;1m"), name, Text("\x1b[m(...)")) : Texts(name, Text("(...)"));
+ }
- Text_t text = Text$format(colorize ? "\x1b[0;1m%s\x1b[m(" : "%s(", type->StructInfo.name);
+ Text_t text = colorize ? Texts(Text("\x1b[0;1m"), name, Text("\x1b[m(")) : Texts(name, Text("("));
ptrdiff_t byte_offset = 0;
ptrdiff_t bit_offset = 0;
for (int i = 0; i < type->StructInfo.num_fields; i++) {
diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c
index c26fd798..226f9ebb 100644
--- a/src/stdlib/tables.c
+++ b/src/stdlib/tables.c
@@ -16,12 +16,13 @@
#include <string.h>
#include <sys/param.h>
-#include "lists.h"
#include "c_strings.h"
#include "datatypes.h"
+#include "lists.h"
#include "memory.h"
#include "metamethods.h"
#include "pointers.h"
+#include "print.h"
#include "siphash.h"
#include "tables.h"
#include "text.h"
@@ -31,7 +32,7 @@
// #define DEBUG_TABLES
#ifdef DEBUG_TABLES
-#define hdebug(fmt, ...) printf("\x1b[2m" fmt "\x1b[m" __VA_OPT__(,) __VA_ARGS__)
+#define hdebug(fmt, ...) print_inline("\x1b[2m", __VA_ARGS__, "\x1b[m")
#else
#define hdebug(...) (void)0
#endif
@@ -87,9 +88,9 @@ static INLINE void hshow(const Table_t *t)
for (uint32_t i = 0; t->bucket_info && i < t->bucket_info->count; i++) {
if (i > 0) hdebug(" ");
if (t->bucket_info->buckets[i].occupied)
- hdebug("[%d]=%d(%d)", i, t->bucket_info->buckets[i].index, t->bucket_info->buckets[i].next_bucket);
+ hdebug("[", i, "]=", t->bucket_info->buckets[i].index, "(", t->bucket_info->buckets[i].next_bucket, ")");
else
- hdebug("[%d]=_", i);
+ hdebug("[", i, "]=_");
}
hdebug("}\n");
}
@@ -114,10 +115,10 @@ PUREFUNC public void *Table$get_raw(Table_t t, const void *key, const TypeInfo_t
uint64_t hash = HASH_KEY(t, key);
hshow(&t);
- hdebug("Getting value with initial probe at %u\n", hash);
+ hdebug("Getting value with initial probe at ", hash, "\n");
bucket_t *buckets = t.bucket_info->buckets;
for (uint64_t i = hash; buckets[i].occupied; i = buckets[i].next_bucket) {
- hdebug("Checking against key in bucket %u\n", i);
+ hdebug("Checking against key in bucket ", i, "\n");
void *entry = GET_ENTRY(t, buckets[i].index);
if (EQUAL_KEYS(entry, key)) {
hdebug("Found key!\n");
@@ -146,7 +147,7 @@ static void Table$set_bucket(Table_t *t, const void *entry, int32_t index, const
const void *key = entry;
bucket_t *buckets = t->bucket_info->buckets;
uint64_t hash = HASH_KEY(*t, key);
- hdebug("Hash value (mod %u) = %u\n", t->bucket_info->count, hash);
+ hdebug("Hash value (mod ", t->bucket_info->count, ") = ", hash, "\n");
bucket_t *bucket = &buckets[hash];
if (!bucket->occupied) {
hdebug("Got an empty space\n");
@@ -158,7 +159,7 @@ static void Table$set_bucket(Table_t *t, const void *entry, int32_t index, const
return;
}
- hdebug("Collision detected in bucket %u (entry %u)\n", hash, bucket->index);
+ hdebug("Collision detected in bucket ", hash, " (entry ", bucket->index, ")\n");
while (buckets[t->bucket_info->last_free].occupied) {
assert(t->bucket_info->last_free > 0);
@@ -167,7 +168,7 @@ static void Table$set_bucket(Table_t *t, const void *entry, int32_t index, const
uint64_t collided_hash = HASH_KEY(*t, GET_ENTRY(*t, bucket->index));
if (collided_hash != hash) { // Collided with a mid-chain entry
- hdebug("Hit a mid-chain entry at bucket %u (chain starting at %u)\n", hash, collided_hash);
+ hdebug("Hit a mid-chain entry at bucket ", hash, " (chain starting at ", collided_hash, ")\n");
// Find chain predecessor
uint64_t predecessor = collided_hash;
while (buckets[predecessor].next_bucket != hash)
@@ -197,7 +198,7 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
{
if (unlikely(new_capacity > TABLE_MAX_BUCKETS))
fail("Table has exceeded the maximum table size (2^31) and cannot grow further!");
- hdebug("About to resize from %u to %u\n", t->bucket_info ? t->bucket_info->count : 0, new_capacity);
+ hdebug("About to resize from ", t->bucket_info ? t->bucket_info->count : 0, " to ", new_capacity, "\n");
hshow(t);
size_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[new_capacity]);
t->bucket_info = GC_MALLOC_ATOMIC(alloc_size);
@@ -206,7 +207,7 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
t->bucket_info->last_free = new_capacity-1;
// Rehash:
for (int64_t i = 0; i < Table$length(*t); i++) {
- hdebug("Rehashing %u\n", i);
+ hdebug("Rehashing ", i, "\n");
Table$set_bucket(t, GET_ENTRY(*t, i), i, type);
}
@@ -318,12 +319,12 @@ public void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type)
// maybe update lastfree_index1 to removed bucket's index
uint64_t hash = HASH_KEY(*t, key);
- hdebug("Removing key with hash %u\n", hash);
+ hdebug("Removing key with hash ", hash, "\n");
bucket_t *bucket, *prev = NULL;
for (uint64_t i = hash; t->bucket_info->buckets[i].occupied; i = t->bucket_info->buckets[i].next_bucket) {
if (EQUAL_KEYS(GET_ENTRY(*t, t->bucket_info->buckets[i].index), key)) {
bucket = &t->bucket_info->buckets[i];
- hdebug("Found key to delete in bucket %u\n", i);
+ hdebug("Found key to delete in bucket ", i, "\n");
goto found_it;
}
if (t->bucket_info->buckets[i].next_bucket == END_OF_CHAIN)
diff --git a/src/stdlib/text.c b/src/stdlib/text.c
index cc4158e5..2b49cc12 100644
--- a/src/stdlib/text.c
+++ b/src/stdlib/text.c
@@ -232,35 +232,6 @@ public int32_t get_synthetic_grapheme(const ucs4_t *codepoints, int64_t utf32_le
#pragma GCC diagnostic pop
#endif
-int text_visualize(FILE *stream, Text_t t, int depth)
-{
- switch (t.tag) {
- case TEXT_ASCII: return fprintf(stream, "<ascii length=%ld>%.*s</ascii>", t.length, t.length, t.ascii);
- case TEXT_GRAPHEMES: {
- int printed = fprintf(stream, "<graphemes length=%ld>", t.length);
- printed += Text$print(stream, t);
- printed += fprintf(stream, "</graphemes>");
- return printed;
- }
- case TEXT_CONCAT: {
- int printed = fprintf(stream, "<concat depth=%ld length=%ld>\n", t.depth, t.length);
- for (int i = 0; i < depth+1; i++)
- printed += fputc(' ', stream);
- printed += text_visualize(stream, *t.left, depth+1);
- printed += fputc('\n', stream);
- for (int i = 0; i < depth+1; i++)
- printed += fputc(' ', stream);
- printed += text_visualize(stream, *t.right, depth+1);
- printed += fputc('\n', stream);
- for (int i = 0; i < depth; i++)
- printed += fputc(' ', stream);
- printed += fprintf(stream, "</concat>");
- return printed;
- }
- default: return 0;
- }
-}
-
public int Text$print(FILE *stream, Text_t t)
{
if (t.length == 0) return 0;
@@ -1389,8 +1360,11 @@ public Text_t Text$quoted(Text_t text, bool colorize, Text_t quotation_mark)
case '\x1C' ... '\x1F': case '\x7F' ... '\x7F': {
if (colorize) ret = concat2_assuming_safe(ret, Text("\x1b[34;1m"));
ret = concat2_assuming_safe(ret, Text("\\x"));
- char tmp[3];
- snprintf(tmp, sizeof(tmp), "%02X", g);
+ char tmp[3] = {
+ (g / 16) > 9 ? 'a' + (g / 16) - 10 : '0' + (g / 16),
+ (g & 15) > 9 ? 'a' + (g & 15) - 10 : '0' + (g & 15),
+ '\0',
+ };
ret = concat2_assuming_safe(ret, Text$from_strn(tmp, 2));
if (colorize)
ret = concat2_assuming_safe(ret, Text("\x1b[0;35m"));
@@ -1472,22 +1446,6 @@ public Text_t Text$join(Text_t glue, List_t pieces)
return result;
}
-__attribute__((format(printf, 1, 2)))
-public Text_t Text$format(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- int len = vsnprintf(NULL, 0, fmt, args);
- va_end(args);
-
- char *str = GC_MALLOC_ATOMIC((size_t)(len+1));
- va_start(args, fmt);
- vsnprintf(str, (size_t)(len+1), fmt, args);
- va_end(args);
- Text_t ret = Text$from_strn(str, (size_t)len);
- return ret;
-}
-
public List_t Text$clusters(Text_t text)
{
List_t clusters = {};
@@ -1529,8 +1487,7 @@ static INLINE const char *codepoint_name(ucs4_t c)
if (found_name) return found_name;
const uc_block_t *block = uc_block(c);
assert(block);
- snprintf(name, UNINAME_MAX, "%s-%X", block->name, c);
- return name;
+ return String(block->name, "-", hex(c, .no_prefix=true, .uppercase=true));
}
public List_t Text$codepoint_names(Text_t text)
diff --git a/src/stdlib/text.h b/src/stdlib/text.h
index 604cea44..ffdebf68 100644
--- a/src/stdlib/text.h
+++ b/src/stdlib/text.h
@@ -61,8 +61,6 @@ Closure_t Text$by_split(Text_t text, Text_t delimiter);
Closure_t Text$by_split_any(Text_t text, Text_t delimiters);
Text_t Text$trim(Text_t text, Text_t to_trim, bool left, bool right);
char *Text$as_c_string(Text_t text);
-__attribute__((format(printf, 1, 2)))
-public Text_t Text$format(const char *fmt, ...);
List_t Text$clusters(Text_t text);
List_t Text$utf32_codepoints(Text_t text);
List_t Text$utf8_bytes(Text_t text);
diff --git a/src/tomo.c b/src/tomo.c
index 48e554b7..816fd78a 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -686,7 +686,8 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l
break;
}
case USE_MODULE: {
- Text_t lib = Text$format("'%s/installed/%s/lib%s%s'", TOMO_HOME, use->path, use->path, SHARED_SUFFIX);
+ Text_t lib = Texts(Text("'" TOMO_HOME "/installed/"),
+ Text$from_str(use->path), Text("/lib"), Text$from_str(use->path), Text(SHARED_SUFFIX "'"));
Table$set(to_link, &lib, ((Bool_t[1]){1}), Table$info(&Text$info, &Bool$info));
List_t children = Path$glob(Path$from_str(String(TOMO_HOME"/installed/", use->path, "/*.tm")));
diff --git a/test/integers.tm b/test/integers.tm
index 9fa5ffc2..6ba1559c 100644
--- a/test/integers.tm
+++ b/test/integers.tm
@@ -39,10 +39,10 @@ func main()
= "1,2,3,4,5,"
>> x := Int64(123)
- >> x.format(digits=5)
- = "00123"
>> x.hex()
= "0x7B"
+ >> x.hex(digits=4)
+ = "0x007B"
>> x.octal()
= "0o173"
diff --git a/test/nums.tm b/test/nums.tm
index 573b50ec..3653f18a 100644
--- a/test/nums.tm
+++ b/test/nums.tm
@@ -14,8 +14,8 @@ func main()
>> Num.PI
= 3.141592653589793
- >> Num.PI.format(precision=10)
- = "3.1415926536"
+ >> Num.PI.with_precision(0.01)
+ = 3.14
>> Num.INF
= Num.INF