Data update

This commit is contained in:
Ingy döt Net 2026-04-30 12:34:36 -04:00
parent 4bb20c9b71
commit cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions

View file

@ -0,0 +1,47 @@
with Ada.Finalization;
package BT is
type Balanced_Ternary is private;
-- conversions
function To_Balanced_Ternary (Num : Integer) return Balanced_Ternary;
function To_Balanced_Ternary (Str : String) return Balanced_Ternary;
function To_Integer (Num : Balanced_Ternary) return Integer;
function To_string (Num : Balanced_Ternary) return String;
-- Arithmetics
-- unary minus
function "-" (Left : in Balanced_Ternary)
return Balanced_Ternary;
-- subtraction
function "-" (Left, Right : in Balanced_Ternary)
return Balanced_Ternary;
-- addition
function "+" (Left, Right : in Balanced_Ternary)
return Balanced_Ternary;
-- multiplication
function "*" (Left, Right : in Balanced_Ternary)
return Balanced_Ternary;
private
-- a balanced ternary number is a unconstrained array of (1,0,-1)
-- dinamically allocated, least significant trit leftmost
type Trit is range -1..1;
type Trit_Array is array (Positive range <>) of Trit;
pragma Pack(Trit_Array);
type Trit_Access is access Trit_Array;
type Balanced_Ternary is new Ada.Finalization.Controlled
with record
Ref : Trit_access;
end record;
procedure Initialize (Object : in out Balanced_Ternary);
procedure Adjust (Object : in out Balanced_Ternary);
procedure Finalize (Object : in out Balanced_Ternary);
end BT;

View file

@ -0,0 +1,181 @@
with Ada.Unchecked_Deallocation;
package body BT is
procedure Free is new Ada.Unchecked_Deallocation (Trit_Array, Trit_Access);
-- Conversions
-- String to BT
function To_Balanced_Ternary (Str: String) return Balanced_Ternary is
J : Positive := 1;
Tmp : Trit_Access;
begin
Tmp := new Trit_Array (1..Str'Last);
for I in reverse Str'Range loop
case Str(I) is
when '+' => Tmp (J) := 1;
when '-' => Tmp (J) := -1;
when '0' => Tmp (J) := 0;
when others => raise Constraint_Error;
end case;
J := J + 1;
end loop;
return (Ada.Finalization.Controlled with Ref => Tmp);
end To_Balanced_Ternary;
-- Integer to BT
function To_Balanced_Ternary (Num: Integer) return Balanced_Ternary is
K : Integer := 0;
D : Integer;
Value : Integer := Num;
Tmp : Trit_Array(1..19); -- 19 trits is enough to contain
-- a 32 bits signed integer
begin
loop
D := (Value mod 3**(K+1))/3**K;
if D = 2 then D := -1; end if;
Value := Value - D*3**K;
K := K + 1;
Tmp(K) := Trit(D);
exit when Value = 0;
end loop;
return (Ada.Finalization.Controlled
with Ref => new Trit_Array'(Tmp(1..K)));
end To_Balanced_Ternary;
-- BT to Integer --
-- If the BT number is too large Ada will raise CONSTRAINT ERROR
function To_Integer (Num : Balanced_Ternary) return Integer is
Value : Integer := 0;
Pos : Integer := 1;
begin
for I in Num.Ref.all'Range loop
Value := Value + Integer(Num.Ref(I)) * Pos;
Pos := Pos * 3;
end loop;
return Value;
end To_Integer;
-- BT to String --
function To_String (Num : Balanced_Ternary) return String is
I : constant Integer := Num.Ref.all'Last;
Result : String (1..I);
begin
for J in Result'Range loop
case Num.Ref(I-J+1) is
when 0 => Result(J) := '0';
when -1 => Result(J) := '-';
when 1 => Result(J) := '+';
end case;
end loop;
return Result;
end To_String;
-- unary minus --
function "-" (Left : in Balanced_Ternary)
return Balanced_Ternary is
Result : constant Balanced_Ternary := Left;
begin
for I in Result.Ref.all'Range loop
Result.Ref(I) := - Result.Ref(I);
end loop;
return Result;
end "-";
-- addition --
Carry : Trit;
function Add (Left, Right : in Trit)
return Trit is
begin
if Left /= Right then
Carry := 0;
return Left + Right;
else
Carry := Left;
return -Right;
end if;
end Add;
pragma Inline (Add);
function "+" (Left, Right : in Trit_Array)
return Balanced_Ternary is
Max_Size : constant Integer :=
Integer'Max(Left'Last, Right'Last);
Tmp_Left, Tmp_Right : Trit_Array(1..Max_Size) := (others => 0);
Result : Trit_Array(1..Max_Size+1) := (others => 0);
begin
Tmp_Left (1..Left'Last) := Left;
Tmp_Right(1..Right'Last) := Right;
for I in Tmp_Left'Range loop
Result(I) := Add (Result(I), Tmp_Left(I));
Result(I+1) := Carry;
Result(I) := Add(Result(I), Tmp_Right(I));
Result(I+1) := Add(Result(I+1), Carry);
end loop;
-- remove trailing zeros
for I in reverse Result'Range loop
if Result(I) /= 0 then
return (Ada.Finalization.Controlled
with Ref => new Trit_Array'(Result(1..I)));
end if;
end loop;
return (Ada.Finalization.Controlled
with Ref => new Trit_Array'(1 => 0));
end "+";
function "+" (Left, Right : in Balanced_Ternary)
return Balanced_Ternary is
begin
return Left.Ref.all + Right.Ref.all;
end "+";
-- Subtraction
function "-" (Left, Right : in Balanced_Ternary)
return Balanced_Ternary is
begin
return Left + (-Right);
end "-";
-- multiplication
function "*" (Left, Right : in Balanced_Ternary)
return Balanced_Ternary is
A, B : Trit_Access;
Result : Balanced_Ternary;
begin
if Left.Ref.all'Length > Right.Ref.all'Length then
A := Right.Ref; B := Left.Ref;
else
B := Right.Ref; A := Left.Ref;
end if;
for I in A.all'Range loop
if A(I) /= 0 then
declare
Tmp_Result : Trit_Array (1..I+B.all'Length-1) := (others => 0);
begin
for J in B.all'Range loop
Tmp_Result(I+J-1) := B(J) * A(I);
end loop;
Result := Result.Ref.all + Tmp_Result;
end;
end if;
end loop;
return Result;
end "*";
procedure Adjust (Object : in out Balanced_Ternary) is
begin
Object.Ref := new Trit_Array'(Object.Ref.all);
end Adjust;
procedure Finalize (Object : in out Balanced_Ternary) is
begin
Free (Object.Ref);
end Finalize;
procedure Initialize (Object : in out Balanced_Ternary) is
begin
Object.Ref := new Trit_Array'(1 => 0);
end Initialize;
end BT;

View file

@ -0,0 +1,19 @@
with Ada.Text_Io; use Ada.Text_Io;
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io;
with BT; use BT;
procedure TestBT is
Result, A, B, C : Balanced_Ternary;
begin
A := To_Balanced_Ternary("+-0++0+");
B := To_Balanced_Ternary(-436);
C := To_Balanced_Ternary("+-++-");
Result := A * (B - C);
Put("a = "); Put(To_integer(A), 4); New_Line;
Put("b = "); Put(To_integer(B), 4); New_Line;
Put("c = "); Put(To_integer(C), 4); New_Line;
Put("a * (b - c) = "); Put(To_integer(Result), 4);
Put_Line (" " & To_String(Result));
end TestBT;

View file

@ -0,0 +1,79 @@
[ -1 1 clamp 1+ ]'[ swap peek do ] is sif ( n --> )
[ $ "" swap witheach
[ sif [ char - char 0 char + ]
swap join ] ] is t->$ ( t --> )
[ [] swap witheach
[ char - - sif [ 1 -1 0 ]
swap join ] ] is $->t ( $ --> t )
[ 0 swap reverse witheach [ swap 3 * + ] ] is t->n ( $ --> t )
[ [] swap
[ 3 /mod [ table 0 1 [ 1+ -1 ] ] do
swap dip join dup 0 = until ]
drop ] is n->t ( n --> t )
[ -1 peek ] is tsign ( t --> n )
[ ' [ 0 ] = ] is tzero ( t --> b )
[ tsign -1 = ] is tneg ( t --> b )
[ tsign 1 = ] is tpos ( t --> b )
[ [] swap witheach [ negate join ] ] is -t ( t --> t )
[ 0 over size times
[ 1 - 2dup peek if conclude ]
1+ dup if split drop ] is tnorm ( t --> t )
[ [] 0 2swap
over size over size - dup 0 <
if [ dip swap negate ]
0 swap of join temp put
witheach
[ temp share i^ peek
+ + 3 +
[ table
[ 0 -1 ] [ 1 -1 ] [ -1 0 ]
[ 0 0 ] [ 1 0 ] [ -1 1 ]
[ 0 1 ] ] do
dip join ]
join tnorm
temp release ] is t+ ( t t --> t )
[ -t t+ ] is t- ( t t --> t )
[ t- tneg ] is t< ( t t --> b )
[ t- tpos ] is t> ( t t --> b )
[ behead swap witheach
[ 2dup t> if swap
drop ] ] is tmin ( [ --> t )
[ behead swap witheach
[ 2dup t< if swap
drop ] ] is tmax ( [ --> t )
[ dup t+ ] is twice ( t --> t )
[ 0 swap join ] is thrice ( t --> t )
[ ' [ 0 ] swap witheach
[ dip over
sif [ t- drop t+ ]
dip thrice ]
nip ] is t* ( t t --> t )
say "a: " $ "+-0++0+" dup echo$ say " = " $->t t->n echo cr
say "b: " -436 dup echo say " = " n->t t->$ echo$ cr
say "c: " $ "+-++-" dup echo$ say " = " $->t t->n echo cr
say "a*(b-c): = "
$ "+-0++0+" $->t
-436 n->t
$ "+-++-" $->t
t- t*
dup t->$ echo$ say " = " t->n echo cr

View file

@ -0,0 +1,138 @@
## BalancedTernary in R (S3)
## Constructor helpers ----
new_BalancedTernary <- function(digits) {
# digits are least-significant first, values in {-1,0,1}
structure(list(digits = as.integer(digits)), class = "BalancedTernary")
}
BalancedTernary <- function(x = 0L) {
if (inherits(x, "BalancedTernary")) return(x)
if (is.character(x)) return(BalancedTernary_from_string(x))
if (length(x) != 1 || !is.finite(x)) stop("BalancedTernary: need a single finite number or a string.")
BalancedTernary_from_int(as.integer(x))
}
BalancedTernary_zero <- function() new_BalancedTernary(0L)
## Conversions ----
BalancedTernary_from_int <- function(n) {
n <- as.integer(n)
if (n == 0L) return(new_BalancedTernary(0L))
digs <- integer(0)
while (n != 0L) {
r <- n %% 3L
if (r == 0L) {
digs <- c(digs, 0L); n <- n %/% 3L
} else if (r == 1L) {
digs <- c(digs, 1L); n <- n %/% 3L
} else { # r == 2 -> digit -1 and carry +1 (i.e., add 1 then divide)
digs <- c(digs, -1L); n <- (n + 1L) %/% 3L
}
}
new_BalancedTernary(digs)
}
BalancedTernary_from_string <- function(s) {
# string is most-significant first with '-', '0', '+'
map <- c("-" = -1L, "0" = 0L, "+" = 1L)
chs <- strsplit(s, "", fixed = TRUE)[[1]]
if (!all(chs %in% names(map))) stop("String may only contain '-', '0', '+'.")
# reverse to least-significant first
new_BalancedTernary(unname(map[rev(chs)]))
}
bt <- function(s) BalancedTernary_from_string(s) # macro-ish convenience
## Printing & coercion ----
print.BalancedTernary <- function(x, ...) {
cat(as.character(x), "\n", sep = "")
invisible(x)
}
as.character.BalancedTernary <- function(x, ...) {
map <- c(`-1` = "-", `0` = "0", `1` = "+")
# display most-significant first
paste0(rev(map[as.character(x$digits)]), collapse = "")
}
as.integer.BalancedTernary <- function(x, ...) {
s <- x$digits
if (length(s) == 1L && s[1] == 0L) return(0L)
ex <- seq_along(s) - 1L
# use double accumulate then coerce to integer (safe for moderate sizes)
val <- sum((3 ^ ex) * s)
as.integer(val)
}
## Unary minus ----
`-.BalancedTernary` <- function(e1) new_BalancedTernary(-e1$digits)
## Core arithmetic helpers ----
# Addition table for (a1 + b1 + c) -> (digit, carry),
# indexed by 4 + a1 + b1 + c where a1,b1,c in {-1,0,1} gives 1..7
.bt_table_digit <- c( 0, 1, -1, 0, 1, -1, 0) # d
.bt_table_carry <- c(-1, -1, 0, 0, 0, 1, 1) # c
.bt_add <- function(a, b, c = 0L) {
# a,b are integer vectors of digits (LSB first) in {-1,0,1}
if (length(a) == 0L || length(b) == 0L) {
if (c == 0L) return(if (length(a) == 0L) b else a)
return(.bt_add(c(c), if (length(a) == 0L) b else a))
} else {
a1 <- a[1]; b1 <- b[1]
idx <- 4L + a1 + b1 + c
d <- .bt_table_digit[idx]
c2 <- .bt_table_carry[idx]
r <- .bt_add(a[-1], b[-1], c2)
if (length(r) != 0L || d != 0L) {
return(c(d, r)) # unshift
} else {
return(r)
}
}
}
.bt_mul <- function(a, b) {
# schoolbook recursion with balanced digits
if (length(a) == 0L || length(b) == 0L) return(integer(0))
a1 <- a[1]
if (a1 == -1L) x <- (-BalancedTernary(new_BalancedTernary(b)))$digits
else if (a1 == 0L) x <- integer(0)
else if (a1 == 1L) x <- b
# shift (multiply by 3) = prepend a 0 digit to recursive product
y <- c(0L, .bt_mul(a[-1], b))
.bt_add(x, y)
}
.normalize_zero <- function(v) if (length(v) == 0L) 0L else v
## Binary operators ----
`+.BalancedTernary` <- function(e1, e2) {
v <- .bt_add(e1$digits, e2$digits)
new_BalancedTernary(.normalize_zero(v))
}
`-.BalancedTernary` # already defined (unary)
`%minus_bt%` <- function(a, b) a + (-b) # internal helper if needed
`*.BalancedTernary` <- function(e1, e2) {
v <- .bt_mul(e1$digits, e2$digits)
new_BalancedTernary(.normalize_zero(v))
}
## Demo / tests ----
a <- bt("+-0++0+")
cat("a: ", as.integer(a), ", ", as.character(a), "\n", sep = "")
b <- BalancedTernary(-436L)
cat("b: ", as.integer(b), ", ", as.character(b), "\n", sep = "")
c <- BalancedTernary("+-++-")
cat("c: ", as.integer(c), ", ", as.character(c), "\n", sep = "")
r <- a * (b + (-c)) # a * (b - c)
cat("a * (b - c): ", as.integer(r), ", ", as.character(r), "\n", sep = "")
stopifnot(as.integer(r) == as.integer(a) * (as.integer(b) - as.integer(c)))

View file

@ -0,0 +1,297 @@
const std = @import("std");
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const stdout = std.io.getStdOut().writer();
var a = try BalancedTernary.fromString(allocator, "+-0++0+");
defer a.deinit();
const a_val = try a.toI128();
const a_str = try a.toString(allocator);
defer allocator.free(a_str);
try stdout.print("a = {s} = {d}\n", .{ a_str, a_val });
var b = try BalancedTernary.fromI128(allocator, -436);
defer b.deinit();
const b_val = try b.toI128();
const b_str = try b.toString(allocator);
defer allocator.free(b_str);
try stdout.print("b = {s} = {d}\n", .{ b_str, b_val });
var c = try BalancedTernary.fromString(allocator, "+-++-");
defer c.deinit();
const c_val = try c.toI128();
const c_str = try c.toString(allocator);
defer allocator.free(c_str);
try stdout.print("c = {s} = {d}\n", .{ c_str, c_val });
var c_neg = try c.clone(allocator);
defer c_neg.deinit();
c_neg.negate();
var b_plus_neg_c = try b.add(allocator, c_neg);
defer b_plus_neg_c.deinit();
var d = try a.mul(allocator, b_plus_neg_c);
defer d.deinit();
const d_val = try d.toI128();
const d_str = try d.toString(allocator);
defer allocator.free(d_str);
try stdout.print("a * (b - c) = {s} = {d}\n", .{ d_str, d_val });
var e = try BalancedTernary.fromString(allocator, "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
defer e.deinit();
const e_result = e.toI128();
try std.testing.expect(e_result == error.Overflow);
}
const Trit = enum {
Zero,
Pos,
Neg,
fn fromChar(c: u8) !Trit {
return switch (c) {
'0' => .Zero,
'+' => .Pos,
'-' => .Neg,
else => error.InvalidCharacter,
};
}
fn toChar(self: Trit) u8 {
return switch (self) {
.Zero => '0',
.Pos => '+',
.Neg => '-',
};
}
fn add(self: Trit, rhs: Trit) struct { carry: Trit, current: Trit } {
return switch (self) {
.Zero => .{ .carry = .Zero, .current = rhs },
.Pos => switch (rhs) {
.Zero => .{ .carry = .Zero, .current = .Pos },
.Neg => .{ .carry = .Zero, .current = .Zero },
.Pos => .{ .carry = .Pos, .current = .Neg },
},
.Neg => switch (rhs) {
.Zero => .{ .carry = .Zero, .current = .Neg },
.Pos => .{ .carry = .Zero, .current = .Zero },
.Neg => .{ .carry = .Neg, .current = .Pos },
},
};
}
fn mul(self: Trit, rhs: Trit) Trit {
return switch (self) {
.Zero => .Zero,
.Pos => switch (rhs) {
.Zero => .Zero,
.Pos => .Pos,
.Neg => .Neg,
},
.Neg => switch (rhs) {
.Zero => .Zero,
.Pos => .Neg,
.Neg => .Pos,
},
};
}
fn negate(self: Trit) Trit {
return switch (self) {
.Zero => .Zero,
.Pos => .Neg,
.Neg => .Pos,
};
}
};
const BalancedTernary = struct {
digits: ArrayList(Trit),
fn deinit(self: *BalancedTernary) void {
self.digits.deinit();
}
fn clone(self: BalancedTernary, allocator: Allocator) !BalancedTernary {
var new_digits = try ArrayList(Trit).initCapacity(allocator, self.digits.items.len);
try new_digits.appendSlice(self.digits.items);
return BalancedTernary{ .digits = new_digits };
}
fn fromString(allocator: Allocator, s: []const u8) !BalancedTernary {
var digits = ArrayList(Trit).init(allocator);
errdefer digits.deinit();
var i: usize = s.len;
while (i > 0) {
i -= 1;
const trit = try Trit.fromChar(s[i]);
try digits.append(trit);
}
return BalancedTernary{ .digits = digits };
}
fn fromI128(allocator: Allocator, x: i128) !BalancedTernary {
var digits = ArrayList(Trit).init(allocator);
errdefer digits.deinit();
var curr = x;
while (true) {
const rem = @rem(curr, 3);
const trit: Trit = switch (rem) {
0 => .Zero,
1, -2 => .Pos,
2, -1 => .Neg,
else => unreachable,
};
try digits.append(trit);
const offset = @as(i128, @intFromFloat(@round(@as(f64, @floatFromInt(rem)) / 3.0)));
curr = @divTrunc(curr, 3) + offset;
if (curr == 0) break;
}
return BalancedTernary{ .digits = digits };
}
fn toString(self: BalancedTernary, allocator: Allocator) ![]const u8 {
var result = try ArrayList(u8).initCapacity(allocator, self.digits.items.len);
defer result.deinit();
var i: usize = self.digits.items.len;
while (i > 0) {
i -= 1;
try result.append(self.digits.items[i].toChar());
}
return result.toOwnedSlice();
}
fn toI128(self: BalancedTernary) !i128 {
var acc: i128 = 0;
for (self.digits.items, 0..) |trit, i| {
const index: u32 = std.math.cast(u32, i) orelse return error.Overflow;
switch (trit) {
.Zero => {},
.Pos => {
const power = std.math.powi(i128, 3, index) catch return error.Overflow;
acc = std.math.add(i128, acc, power) catch return error.Overflow;
},
.Neg => {
const power = std.math.powi(i128, 3, index) catch return error.Overflow;
acc = std.math.sub(i128, acc, power) catch return error.Overflow;
},
}
}
return acc;
}
fn trim(digits: *ArrayList(Trit)) void {
while (digits.items.len > 0) {
const last = digits.items[digits.items.len - 1];
if (last != .Zero) {
break;
}
_ = digits.pop();
}
}
fn add(self: BalancedTernary, allocator: Allocator, rhs: BalancedTernary) !BalancedTernary {
if (rhs.digits.items.len == 0) {
if (self.digits.items.len == 0) {
var digits = ArrayList(Trit).init(allocator);
try digits.append(.Zero);
return BalancedTernary{ .digits = digits };
}
return try self.clone(allocator);
}
const length = @min(self.digits.items.len, rhs.digits.items.len);
var sum = ArrayList(Trit).init(allocator);
errdefer sum.deinit();
var carry = ArrayList(Trit).init(allocator);
errdefer carry.deinit();
try carry.append(.Zero);
for (0..length) |i| {
const result = self.digits.items[i].add(rhs.digits.items[i]);
try sum.append(result.current);
try carry.append(result.carry);
}
if (self.digits.items.len > length) {
try sum.appendSlice(self.digits.items[length..]);
}
if (rhs.digits.items.len > length) {
try sum.appendSlice(rhs.digits.items[length..]);
}
trim(&sum);
trim(&carry);
var sum_bt = BalancedTernary{ .digits = sum };
const carry_bt = BalancedTernary{ .digits = carry };
//defer carry_bt.deinit();
return try sum_bt.add(allocator, carry_bt);
}
fn mul(self: BalancedTernary, allocator: Allocator, rhs: BalancedTernary) !BalancedTernary {
var results = ArrayList(BalancedTernary).init(allocator);
defer {
for (results.items) |*item| {
item.deinit();
}
results.deinit();
}
for (rhs.digits.items, 0..) |rhs_trit, i| {
var digits = ArrayList(Trit).init(allocator);
errdefer digits.deinit();
for (0..i) |_| {
try digits.append(.Zero);
}
for (self.digits.items) |self_trit| {
try digits.append(self_trit.mul(rhs_trit));
}
try results.append(BalancedTernary{ .digits = digits });
}
var acc_digits = ArrayList(Trit).init(allocator);
try acc_digits.append(.Zero);
var acc = BalancedTernary{ .digits = acc_digits };
for (results.items) |item| {
const new_acc = try acc.add(allocator, item);
acc.deinit();
acc = new_acc;
}
return acc;
}
fn negate(self: *BalancedTernary) void {
for (self.digits.items) |*trit| {
trit.* = trit.negate();
}
}
};