Metadata-Version: 2.4
Name: balanced-ternary
Version: 0.2.0
Summary: Balanced ternary number type for Python: T-notation, conversions, and full digit-level arithmetic (digits -1, 0, 1).
Project-URL: Homepage, https://github.com/amaar-mc/balanced-ternary
Project-URL: Repository, https://github.com/amaar-mc/balanced-ternary
Project-URL: Bug Tracker, https://github.com/amaar-mc/balanced-ternary/issues
Author-email: Amaar Chughtai <amaardevx@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Amaar Chughtai
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: arithmetic,balanced-ternary,mathematics,number-systems,numeral-systems,ternary
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: hypothesis>=6.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.4.0; extra == 'dev'
Description-Content-Type: text/markdown

# balanced-ternary

<p align="center">
  <img src="assets/logo.png" alt="balanced-ternary logo" width="160">
</p>

A pure-Python implementation of balanced ternary arithmetic. The `BalancedTernary`
type uses digits from the set {-1, 0, 1}, writes -1 as `T` in T-notation, and
implements addition and multiplication at the digit level with balanced-ternary
carry logic -- not by converting to int and back.

## What is balanced ternary?

Balanced ternary is a non-standard positional numeral system where each digit
(trit) is one of {-1, 0, 1}. The value -1 is conventionally written as `T`.
The value of a balanced ternary numeral is the sum of each digit times its
corresponding power of 3.

```
"1TT" = 1*9 + (-1)*3 + (-1)*1 = 9 - 3 - 1 = 5
"T1T" = (-1)*9 + 1*3 + (-1)*1 = -9 + 3 - 1 = -7
"1T"  = 1*3 + (-1)*1 = 3 - 1 = 2
```

Every integer has a unique balanced ternary representation, and negation is
exact -- just flip the sign of every digit.

## Installation

```
pip install balanced-ternary
```

Or with uv:

```
uv add balanced-ternary
```

## Quick start

```python
from balanced_ternary import BalancedTernary

# Convert from int
a = BalancedTernary.from_int(5)
print(a.to_str())  # "1TT"

# Convert from T-notation string
b = BalancedTernary.from_str("1T")
print(b.to_int())  # 2

# Arithmetic (digit-level carry logic)
print((a + b).to_int())   # 7
print((a - b).to_int())   # 3
print((a * b).to_int())   # 10

# Negation is exact -- just flip digit signs
print((-a).to_str())      # "T11"  (-5 in balanced ternary)

# T-notation input supports lowercase t
c = BalancedTernary.from_str("1t0T")
print(c.to_int())  # 23

# Ordering: compare and sort by integer value
x = BalancedTernary.from_int(3)
y = BalancedTernary.from_int(7)
print(x < y)   # True
print(x >= y)  # False
values = [BalancedTernary.from_int(n) for n in [5, -2, 0, 3]]
print([v.to_int() for v in sorted(values)])  # [-2, 0, 3, 5]

# Floored division and modulo (Python semantics: remainder has sign of divisor)
d = BalancedTernary.from_int(7)
e = BalancedTernary.from_int(2)
print((d // e).to_int())   # 3
print((d % e).to_int())    # 1
q, r = divmod(d, e)
print(q.to_int(), r.to_int())  # 3 1

# Negative divisor: remainder is non-positive (Python floored convention)
f = BalancedTernary.from_int(-2)
print((d // f).to_int())   # -4
print((d % f).to_int())    # -1
```

## API

### `BalancedTernary.from_int(value: int) -> BalancedTernary`

Convert any Python int to balanced ternary.

### `BalancedTernary.from_str(text: str) -> BalancedTernary`

Parse a T-notation string. Valid characters are `0`, `1`, `T`, `t`. The
string is most-significant-first. Raises `ValueError` on empty input or
invalid characters.

### `to_int() -> int`

Return the integer value.

### `to_str() -> str`

Return the canonical T-notation string (most-significant-first, no leading
zeros except for the value zero itself).

### Operators

| Operator | Meaning                         |
|----------|---------------------------------|
| `+`      | Addition                        |
| `-`      | Subtraction                     |
| `*`      | Multiplication                  |
| `//`     | Floored integer division        |
| `%`      | Floored modulo (remainder sign matches divisor) |
| `divmod()` | Returns `(quotient, remainder)` as `BalancedTernary` values |
| unary `-`| Negation (exact, no carry needed) |
| `==`     | Equality                        |
| `<`, `<=`, `>`, `>=` | Ordering by integer value (sortable) |
| `hash()` | Hashable (usable as dict key)   |
| `repr()` | `BalancedTernary.from_str('...')` |
| `str()`  | T-notation string               |

**Division sign convention:** `//` and `%` follow Python's floored division: the
remainder always has the same sign as the divisor. For example, `(-7) // 2 == -4`
and `(-7) % 2 == 1`. `__truediv__` (`/`) is intentionally omitted -- `BalancedTernary`
is an exact integer type and true division would break the exact-arithmetic contract
for most operand pairs.

## Digit-level carry logic

When adding two balanced-ternary digits plus a carry, the column sum `s` is
mapped as follows:

| s  | result digit | carry out |
|----|--------------|-----------|
| -3 | 0            | -1        |
| -2 | 1            | -1        |
| -1 | -1           | 0         |
| 0  | 0            | 0         |
| 1  | 1            | 0         |
| 2  | -1           | 1         |
| 3  | 0            | 1         |

Multiplication uses digit-by-digit partial products accumulated with the
addition logic above.

## Development

```
git clone https://github.com/amaar-mc/balanced-ternary
cd balanced-ternary
uv pip install -e ".[dev]"
uv run pytest -q
uv run ruff check .
uv run mypy src
```

## License

MIT. See [LICENSE](LICENSE).
