Balanced Ternary in MATLAB
I wanted to do something with balanced ternary the other day, so I wrote this MATLAB class.
classdef bt
% Class for managing numbers in balanced ternary.
%
properties (SetAccess='private')
trits = '';
end
methods
function obj=bt(args)
% Constructor. There are two forms. One takes a double
% containing an integer value. The other takes a string
% containing the characters u, n, and o.
%
if (isa(args,'char') && size(args,1) == 1)
if ~all(args=='u' | args=='o' | args=='n')
error('bad trits')
end
obj.trits = trim_leading(args);
elseif (isa(args,'double') && numel(args) == 1)
obj.trits = trim_leading(double_to_trits(args));
end
end
function disp(obj)
% Display method
%
disp(obj.trits)
end
function r = double(obj)
% Convert to double
%
t = obj.trits;
r = 0;
while ~isempty(t)
r = r*3;
if (t(1) == 'u')
r = r+1;
elseif (t(1) == 'n')
r = r-1;
end
t = t(2:end);
end
end
function r = plus(a,b)
% Plus operator.
%
% addition table for balanced ternary
% + n o u
% n nu n o
% o n o u
% u o u un
%
r_lut = ['u' 'n' 'o' 'n' 'o' 'u' 'o' 'u' 'n'];
c_lut = ['n' 'o' 'o' 'o' 'o' 'o' 'o' 'o' 'u'];
% Normalize the 2 inputs to the longest+1 by
% padding with 'o's.
al = size(a.trits,2);
bl = size(b.trits,2);
len = 1+max(al,bl);
a = [repmat('o',1,len-al) a.trits];
b = [repmat('o',1,len-bl) b.trits];
% convert to numbers
va = repmat(2,1,len) - (a=='n') + (a=='u');
vb = repmat(2,1,len) - (b=='n') + (b=='u');
% sum and convert into lut indices
v = 1+(va-1)+3*(vb-1);
% do the lookup
r = bt(r_lut(v));
% check for carries
c = c_lut(v);
if any(c~='o')
r = r + bt([c(2:end) 'o']);
end
end
function r = ne(a,b)
% Not equal operator
%
al = size(a.trits,2);
bl = size(b.trits,2);
len=max(al,bl);
atrits = a.trits;
btrits = b.trits;
if (al ~= len)
atrits = [repmat('o',1,len-al) atrits];
end
if (bl ~= len)
btrits = [repmat('o',1,len-bl) btrits];
end
r = atrits ~= btrits;
end
end
end
function d = trim_leading(s)
start = regexp(s,'[nu][nuo]*','start');
d = s(start:end);
end
function trits = double_to_trits(src)
trits = [];
target = src;
pos = 0;
val = 1;
goal = 2*target;
if (goal < 0)
goal = -goal;
end
while ((val= 0)
if (abs(target-val) < abs(target))
if (val > 0)
trits = [trits 'u'];
target = target-val;
else
trits = [trits 'n'];
target = target-val;
end
else
trits = [trits 'o'];
end
val = val/3;
pos = pos-1;
if ((target*val) < 0)
val = -val;
end
end
end
Now I can do things like this:
>> x = bt(512) x = unouoon >> x + x ans = uuunonu >> double(ans) ans = 1024
Pretty neat, huh?