tritlib 2.1.1__tar.gz → 2.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tritlib-2.1.1 → tritlib-2.1.2}/CHANGELOG.md +11 -4
- {tritlib-2.1.1 → tritlib-2.1.2}/PKG-INFO +4 -4
- {tritlib-2.1.1 → tritlib-2.1.2}/README.md +2 -2
- {tritlib-2.1.1 → tritlib-2.1.2}/pyproject.toml +11 -1
- tritlib-2.1.1/.claude/settings.local.json +0 -9
- tritlib-2.1.1/CLAUDE.md +0 -79
- {tritlib-2.1.1 → tritlib-2.1.2}/.gitignore +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/LICENSE +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/__init__.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/context.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/__init__.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/base.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/bochvar.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/heyting.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/kleene.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/lukasiewicz.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/plural.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/logic/rm3.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2/src/tritlib}/py.typed +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/tfloat.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/trit.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/tritarray.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/trits.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/trybble.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/tryte.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/src/tritlib/word.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_context.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_logic.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_logic_kleene.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_plural.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_tfloat.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_tfloat_add.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_tfloat_div.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_tfloat_mul.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_trit.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_tritarray.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_trits.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_tryte.py +0 -0
- {tritlib-2.1.1 → tritlib-2.1.2}/tests/test_word.py +0 -0
|
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.1.2] — 2026-11-04
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `py.typed` is now shipped in the wheel.
|
|
12
|
+
- The sdist no longer includes local tool configuration
|
|
13
|
+
|
|
7
14
|
## [2.1.1] — 2026-07-21
|
|
8
15
|
|
|
9
16
|
### Fixed
|
|
@@ -12,7 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
|
|
|
12
19
|
the dividend. 2.1.0 fixed the quotient decision but kept correcting
|
|
13
20
|
the remainder only after the loop, one unit at a time, against a
|
|
14
21
|
drift that triples per trit: `divmod(TritArray(-2586565449575, 27),
|
|
15
|
-
|
|
22
|
+
TritArray(-4, 27))` needed ~10¹² iterations, i.e. never returned.
|
|
16
23
|
The result was correct whenever it did return, so the identity
|
|
17
24
|
`a == b·q + r` kept the bug hidden.
|
|
18
25
|
|
|
@@ -31,15 +38,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
|
|
|
31
38
|
|
|
32
39
|
### Documentation
|
|
33
40
|
|
|
34
|
-
- `Trits.__divmod__`, `TritArray.__divmod__` and the
|
|
35
|
-
|
|
41
|
+
- `Trits.__divmod__`, `TritArray.__divmod__` and the _Division
|
|
42
|
+
pitfalls_ section of `CLAUDE.md` described the 2.1.0 state, where the
|
|
36
43
|
magnitude comparison alone was believed to maintain
|
|
37
44
|
`|pr| ≤ |d| / 2`. They now document why it does not, and record the
|
|
38
45
|
even-divisor case as the reason to test small even divisors
|
|
39
46
|
explicitly: random fuzzing essentially never draws 2, 4 or 6, which
|
|
40
47
|
is how this survived a full pass.
|
|
41
48
|
- Documented that an even divisor admits two valid `(quotient,
|
|
42
|
-
|
|
49
|
+
remainder)` pairs when the remainder reaches exactly `|d| / 2`, and
|
|
43
50
|
which one this implementation returns —
|
|
44
51
|
`divmod(Trits(10), Trits(4))` is `(3, -2)`, not `(2, 2)`.
|
|
45
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: tritlib
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: Balanced ternary arithmetic and multi-valued logic library
|
|
5
5
|
Project-URL: Homepage, https://codeberg.org/setnex-org/tritlib
|
|
6
6
|
Project-URL: Repository, https://codeberg.org/setnex-org/tritlib
|
|
@@ -20,7 +20,7 @@ Requires-Dist: pytest; extra == 'dev'
|
|
|
20
20
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
|
|
23
|
-
# tritlib — v2.
|
|
23
|
+
# tritlib — v2.1
|
|
24
24
|
|
|
25
25
|
A pure Python library for balanced ternary arithmetic, multi-valued logic, and floating-point representation.
|
|
26
26
|
|
|
@@ -62,7 +62,7 @@ tritlib provides the building blocks for balanced ternary processor simulation:
|
|
|
62
62
|
- Per-trit access (`__getitem__`) and immutable modification (`set`)
|
|
63
63
|
- Sign extraction and absolute value
|
|
64
64
|
- Consensus / anti-consensus (trit-level agreement detection)
|
|
65
|
-
- Logic system dispatch independent of data types (
|
|
65
|
+
- Logic system dispatch independent of data types (mirrors the per-instruction logic selector of the Setnex ISA)
|
|
66
66
|
- Tekum floating-point decode/encode for FPU simulation
|
|
67
67
|
|
|
68
68
|
## Installation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# tritlib — v2.
|
|
1
|
+
# tritlib — v2.1
|
|
2
2
|
|
|
3
3
|
A pure Python library for balanced ternary arithmetic, multi-valued logic, and floating-point representation.
|
|
4
4
|
|
|
@@ -40,7 +40,7 @@ tritlib provides the building blocks for balanced ternary processor simulation:
|
|
|
40
40
|
- Per-trit access (`__getitem__`) and immutable modification (`set`)
|
|
41
41
|
- Sign extraction and absolute value
|
|
42
42
|
- Consensus / anti-consensus (trit-level agreement detection)
|
|
43
|
-
- Logic system dispatch independent of data types (
|
|
43
|
+
- Logic system dispatch independent of data types (mirrors the per-instruction logic selector of the Setnex ISA)
|
|
44
44
|
- Tekum floating-point decode/encode for FPU simulation
|
|
45
45
|
|
|
46
46
|
## Installation
|
|
@@ -2,9 +2,19 @@
|
|
|
2
2
|
requires = ["hatchling"]
|
|
3
3
|
build-backend = "hatchling.build"
|
|
4
4
|
|
|
5
|
+
[tool.hatch.build.targets.sdist]
|
|
6
|
+
include = [
|
|
7
|
+
"src/",
|
|
8
|
+
"tests/",
|
|
9
|
+
"CHANGELOG.md",
|
|
10
|
+
"LICENSE",
|
|
11
|
+
"README.md",
|
|
12
|
+
"pyproject.toml",
|
|
13
|
+
]
|
|
14
|
+
|
|
5
15
|
[project]
|
|
6
16
|
name = "tritlib"
|
|
7
|
-
version = "2.1.
|
|
17
|
+
version = "2.1.2"
|
|
8
18
|
description = "Balanced ternary arithmetic and multi-valued logic library"
|
|
9
19
|
readme = "README.md"
|
|
10
20
|
license = "MIT"
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(python -)",
|
|
5
|
-
"Bash(timeout 400 /home/newick/Programmes/setnex/tritlib/.venv/bin/python -m pytest test_regressions.py -q -p no:cacheprovider --timeout=60)",
|
|
6
|
-
"Bash(timeout 400 /home/newick/Programmes/setnex/tritlib/.venv/bin/python -m pytest test_regressions.py -q -p no:cacheprovider -k \"not full_width and not remainder_is_reduced\")"
|
|
7
|
-
]
|
|
8
|
-
}
|
|
9
|
-
}
|
tritlib-2.1.1/CLAUDE.md
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Règle absolue
|
|
6
|
-
|
|
7
|
-
**Il t'est interdit de coder.** Tu ne dois jamais modifier la logique d'un fichier `.py` de ce dépôt. La seule modification autorisée dans un fichier `.py` est l'écriture ou la mise à jour de **docstrings**, et uniquement lorsque l'utilisateur le demande explicitement. Toute autre édition de code (ajout/suppression de fonctions, modification d'une expression, refactoring, correction de bug, etc.) est interdite, même si elle semble triviale ou évidente. Lecture, recherche, analyse et explication restent autorisées.
|
|
8
|
-
|
|
9
|
-
## Commands
|
|
10
|
-
|
|
11
|
-
Setup and test:
|
|
12
|
-
```bash
|
|
13
|
-
python -m venv .venv
|
|
14
|
-
source .venv/bin/activate
|
|
15
|
-
pip install -e ".[dev]"
|
|
16
|
-
python -m pytest # full suite
|
|
17
|
-
python -m pytest tests/test_tfloat.py # single file
|
|
18
|
-
python -m pytest tests/test_tfloat.py::test_name # single test
|
|
19
|
-
python -m pytest --cov=tritlib # with coverage
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Build distribution: `python -m build` (hatchling backend, declared in `pyproject.toml`).
|
|
23
|
-
|
|
24
|
-
Python ≥ 3.11 required. No runtime dependencies — only `pytest` and `pytest-cov` for dev.
|
|
25
|
-
|
|
26
|
-
## Architecture
|
|
27
|
-
|
|
28
|
-
### Layering of the core types
|
|
29
|
-
|
|
30
|
-
`Trit` → `Trits` → `TritArray` → `TFloat`. Each layer is built on the one below and they must be edited consistent with that direction:
|
|
31
|
-
|
|
32
|
-
- **`Trit`** (`trit.py`) — single balanced ternary digit ∈ {N, Z, P}. Provides `half_add`/`full_add` returning `(sum, carry)` where carry is itself a Trit (ternary carry, not binary).
|
|
33
|
-
- **`Trits`** (`trits.py`) — arbitrary-precision balanced ternary integer, built as a tuple of `Trit` in **little-endian** order. Division uses the double trial quotient method; result follows symmetric Euclidean semantics (remainder may be negative).
|
|
34
|
-
- **`TritArray`** (`tritarray.py`) — fixed-width register-like word at arbitrary width. Three addition modes (`__add__` truncates, `add_with_carry` returns `(result, carry: Trit)`, `add_saturating` clamps). Operations construct via `type(self)._from_trits(trits, width)` (subclass-preserving dispatch) which truncates rather than raising — this is intentional hardware simulation behaviour.
|
|
35
|
-
- **`Trybble`** / **`Tryte`** / **`Word`** (`trybble.py`, `tryte.py`, `word.py`) — width-locked subclasses (3 / 9 / 27 trits) aligned with Setnex ISA v0.8. Each declares a `WIDTH` class attribute, an `__init__(self, value)` that forwards to `TritArray.__init__(value, WIDTH)`, and an override of `_from_trits` that ignores any `width` argument and forces `WIDTH`. Arithmetic between same-typed instances preserves the subtype via `type(self)._from_trits`. `to_width(w)` on a subclass returns a base `TritArray` (changing width exits the locked contract).
|
|
36
|
-
- **`TFloat`** (`tfloat.py`) — Tekum tapered precision float (arXiv:2512.10964). Stores raw as a `TritArray` (even width ≥ 8, not necessarily 9 or 27). Regime/exponent/fraction/sign are properties derived on demand. Arithmetic (`+`, `*`, `/`) is implemented natively at the trit level via `TritArray` operations (mantissa, double-width products, work-scale bounds), then re-encoded through `_finalize`.
|
|
37
|
-
|
|
38
|
-
All types are **immutable**: `__setattr__` raises, `__slots__` enforces fields, and every operation returns a new instance. Do not add mutators.
|
|
39
|
-
|
|
40
|
-
Internal storage is **little-endian** (least significant trit first), but string repr and constructor input strings are **big-endian** (`"+-0+"` reads MSB-to-LSB). Watch this direction reversal when editing.
|
|
41
|
-
|
|
42
|
-
### Logic-system dispatch
|
|
43
|
-
|
|
44
|
-
The five logic systems live in `src/tritlib/logic/`. Each subclasses `TernaryLogic` (in `base.py`) and only needs to override the operators where it diverges from defaults (most override only `imply_op`).
|
|
45
|
-
|
|
46
|
-
`Trit`'s `&`, `|`, `~`, and `imply` look up the active logic via a `ContextVar` (`_current_logic` in `context.py`). When unset, fast inlined Kleene paths are used (no dispatch overhead). The `logic_mode(system)` context manager swaps the active system for the duration of a `with` block. New logic systems should be added by subclassing `TernaryLogic` and exporting from `logic/__init__.py`.
|
|
47
|
-
|
|
48
|
-
`pluralize` (in `logic/plural.py`) evaluates a callable across all five systems and reports convergence/divergence — use it when reasoning about whether an expression is logic-system-sensitive.
|
|
49
|
-
|
|
50
|
-
### Tekum format invariants
|
|
51
|
-
|
|
52
|
-
When touching `TFloat`:
|
|
53
|
-
- Width must be **even and ≥ 8**. Constructors validate this.
|
|
54
|
-
- Three special values are stored as the raw `Tryte`: zero (all Z), infinity (all P), NaR (all N). The `_special` slot caches which one. Arithmetic on specials follows **wheel-algebra** semantics (e.g., `x/0 = ∞`, `0/0 = NaR`, `∞/∞ = NaR`) — see `__add__`, `__mul__`, `__truediv__` for the dispatch tables.
|
|
55
|
-
- Tekum's defining property: **truncation is rounding**. When reducing precision, slice the anchor; no carry propagation needed. The `_finalize` helper centralises this.
|
|
56
|
-
- Cross-width `==` returns `NotImplemented` (no silent coercion).
|
|
57
|
-
- `from_float` is the private `_from_float` since 1.3.0; external callers should use the `TFloat(value, width=…)` constructor.
|
|
58
|
-
|
|
59
|
-
### Division pitfalls (Trits / TritArray)
|
|
60
|
-
|
|
61
|
-
There is exactly **one** division algorithm, in `Trits.__divmod__`. `TritArray.__divmod__` converts both operands with `to_trits()`, divides there, and packs the results back at the operand width (both always fit, so nothing is truncated). Do not reintroduce a second, fixed-width implementation: the partial remainder reaches `1.5 × |d|` mid-loop, so a `TritArray` comparison at the operand width wraps silently and returns an unreduced remainder — the identity `a == b·q + r` still holds, which is why it hid behind the tests for so long.
|
|
62
|
-
|
|
63
|
-
Four things in `Trits.__divmod__` are load-bearing:
|
|
64
|
-
|
|
65
|
-
- **The quotient trit is chosen by magnitude**, comparing `V + V` against `±|d|` where `V = 3·pr + t` is the partial remainder scaled by 3 plus the next dividend trit. Deciding on the sign of the leading trit alone (the pre-2.1.0 code) triples the partial remainder at each step — a 52-trit division drifted to `4·10²² × |d|` and never terminated in practice.
|
|
66
|
-
- **The quotient is accumulated, not collected**: `q = q·3 ± 1`, never a list of trits appended to. A trit pushed into a list can no longer be revised, and the next point depends on revising it.
|
|
67
|
-
- **The remainder is corrected inside the loop, not after it.** One trit cannot always reduce `V`: with `|pr| ≤ |d|/2` the scaled value reaches `1.5·|d| + 1`, while the three possible trits only span `[−1.5·|d|, +1.5·|d|]`. The overshoot is by exactly 1, and it is reachable **for every even divisor** (odd divisors are safe, since `|pr| ≤ (|d|−1)/2` keeps `|V|` in range). The inner loop writes what amounts to a quotient digit of ±2 at that rank; `q + Trits(1)` renormalises it by carrying into the ranks already produced, which balanced ternary addition does for free. It runs at most once per trit. Correcting only at the end still terminates, but one unit at a time against a drift that triples per trit: a 27-trit division by 2 needs ~10¹² iterations, i.e. never. This was the 2.1.1 fix; `2.1.0` shipped the magnitude comparison alone and was still unusable for even divisors.
|
|
68
|
-
- **Every trit of the dividend is consumed**, starting from `q = pr = Trits(0)`. Do not "optimise" back either the `partial_rest = s[:len(d)-1]` pre-load or the `if len(self) < len(other): return Trits(0), self` shortcut; the latter returned an unreduced remainder (`34 / 58` gave `(0, 34)` instead of `(1, −24)`), i.e. a second remainder convention inside the same function.
|
|
69
|
-
|
|
70
|
-
Remainder semantics are symmetric/balanced: `|r| ≤ |b|/2`, so the remainder takes whichever sign minimises its magnitude — **not** the sign of the dividend (`divmod(Trits(-200), Trits(-57)) == (Trits(4), Trits(28))`). For an even divisor the remainder can hit exactly `|b|/2`, where two `(q, r)` pairs satisfy the contract; the loop's own choice is what ships (`divmod(Trits(10), Trits(4)) == (Trits(3), Trits(-2))`). Do not freeze the other one in a test.
|
|
71
|
-
|
|
72
|
-
Any test touching division must assert `2·|r| ≤ |b|` alongside `b·q + r == a`. The identity alone passes even when the algorithm is broken — it held throughout both the 2.1.0 and 2.1.1 bugs. Test small **even** divisors explicitly, at full width: random divisors essentially never hit 2, 4 or 6, which is how the even-divisor case survived a full fuzzing pass.
|
|
73
|
-
|
|
74
|
-
## Conventions to follow
|
|
75
|
-
|
|
76
|
-
- Type-hinted, immutable, dunder-rich public API. Add `__hash__`, `__eq__`, and `@total_ordering` where comparable; raise `AttributeError` from `__setattr__`.
|
|
77
|
-
- Operators returning `NotImplemented` (not raising) for unsupported operand types — except `__divmod__`, which raises `TypeError` to match Python's `divmod` protocol.
|
|
78
|
-
- New public symbols must be re-exported from the appropriate `__init__.py` and added to `__all__`.
|
|
79
|
-
- Docstrings on public classes and methods; the project ships `py.typed` for downstream mypy users.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|