Enumerating Trinary Logic

Kurt Nalty
July 19, 2012

Trinary logic is an extension of binary logic to have three states, such as

<spin up>, <no particle>, and <spin down>.

As implied by this example, quantum computers are expected to utilize trinary logic.

This paper looks at the fundamentals of trinary logic without any attachment to linguistics or philosophy. The primary tool I use, is simple enumeration, accompanied with graphical interpretation of the meanings of the tables. As an assistance in the explanations, I begin with binary logic to develop the method in familiar territory, and then do the same process in trinary. We illustrate the 27 single input trinary gates, then provide the algorithim for the 19683 dual input trinary gates. We list and explain the commutative and associative subset of those gates, then close by presenting two of at least six approaches toward arbitrary logic using a mere handful of gates.

*********************************************************************

Binary logic has two logic states, 0 and 1. We can easily enumerate all binary logic for single input, single output gates.

Input   GND  	WIRE  	NOT  	VCC

0 0 0 1 1
1 0 1 0 1

The GND gate has an output always low, like a ground connection in a logic circuit. The WIRE gate has input and output equal, similar to a wire. The NOT gate is an inverter. Notice that two NOT gates cascaded one into the other make a WIRE gate. This implies that we can treat the NOT gate as a square root of the WIRE. Finally, VCC is stuck high all the time, like a power supply connection in digital logic. There is no way to make GND or VCC from the WIRE and NOT gates. Any single input gates above do not generate the complete set. However, if you provide a NOT gate, and a single static level, such as GND, you can generate the WIRE signal and the VCC signal.

*********************************************************************

Now, let's enumerate the full set of two input binary logic gates.

                    N       N                   X                   N       
INPUTS G A A B B A X N N N B N A A V
N N I I O O O O A I B I N C
A B D D B A R R R R A B D C

0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1


CA CA xx xA xx xA CA CA Cx CA xx xx xx xx Cx CA



The implication gates are not widely used in digital logic, usually showing as single bubble input AND, NAND, OR and NOR gates. (1BAND, 1BNAND, 1BOR, 1BNOR).

In formal logic, we have various material implication gates:
AIB = A implies B 
BIA = B implies A
NAIB = negated A implies B
NBIA = negated B implies A

Under the truth tables are the letters C for commutative, A for associative and x for the absense of the afore properties.

C = 1 iff F(A,B) == F(B,A)
A = 1 iff F(F(A,B),C) == F(A,F(B,C))

Of the above gates, the NAND and NOR gates are capable of generating every logic element in the single and double input cases (including VCC and GND). These are the universal gates, or set generators for logic. All higher input count logic can also be generated by sum of products (or product of sums) formats, and implemented as NAND gates for sum of products, or NOR gates for product of sums expressions.

Technology wise, NAND gates are faster than NOR gates, and thus we find NAND gates as the preferred logic element.

*********************************************************************

Now, let's investigate trinary logic.

By analogy with the example above, let's begin with enumerating the full set of single input and single output gates.

The single input can have three states, which I will label 0,1 and 2. (Simple text editor substitution can change these tables to +, 0 and -.) The output columns will cover a three character counting sequence, for 27 (27=3^3) logic functions.

                                                                                 
I
N W N N N
P I O O C O
U R T T C C T
T 0 E 0 2 1 W W 1 2

0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
1 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2
2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2



At first glance, 27 single input, single output functions may seem like a surplus, but due to the comprehensive nature of enumeration, this is *exactly* what is required to span this functional space.


*********************************************************************

I start by looking at the information preserving gates, where we have all three states possible on the output.

The WIRE gate, where input and outputs are equal, is immediately apparent.

In binary logic, we had a single NOT gate, which squared, gave us a wire. In trinary, we have three NOT gates which square to a WIRE, being NOT0, NOT1 and NOT2. The number after the NOT gives the invariant logic level, while the other two levels swap. When people are initially discussing trinary logic, they usually identify NOT1, and fail to notice the equally valid and necessary NOT0 and NOT2. Cascade two of the very same NOTx together, and you get a WIRE. Consequently, we have three distinct square roots of the wire in trinary.

NOT0->NOT0 = WIRE
NOT1->NOT1 = WIRE
NOT2->NOT2 = WIRE

The remaining two information preserving gates, I've labelled as CW for clockwise, and CCW for counter-clockwise. These rotate the three logic levels in different directions, and constitute two different cubed roots of the wire.

CW->CW->CW = WIRE             CCW->CCW->CCW = WIRE

Cascading different NOTx gates leads to CW and CCW gates.

NOT0->NOT1 = CW     NOT1->NOT0 = CCW
NOT1->NOT2 = CW NOT2->NOT1 = CCW
NOT2->NOT0 = CW NOT0->NOT2 = CCW
These information preserving gates, I collectively call "threefer" gates, as they transfer three levels.

*********************************************************************

Now, let's look at the static levels 0 (0 0 0), 1 (1, 1, 1) and 2 (2, 2, 2). These are like the VCC and GND levels from binary logic, and our new logic level. Since these ignore the inputs, they necessarily totally lose incoming, yet originate outgoing, information. These static level gates, I collectively call "onefer" gates.

*********************************************************************

The last class of gates, I collectively call the twofer gates, as we have two of one logic level, and one of another. We necessarily lose information using these gates.

Before presenting the truth table for the cascade of single input gates, I want to present some graphical tiles, which I've made for the open-source DIA program. These tiles are inspired by similar tiles used in knots and braids. <!-- KN - find references and give credit.-->

The number on top of the tiles is the enumeration value in base 3 for that particular gate. The left side shows incoming logic levels, 0 at the top, 1 in the middle, and 2 at the bottom. The right side shows corresponding output logic levels, 0 at the top, 1 in the middle, and 2 at the bottom. The enumeration function and the tile are related as follows:
Looking at the top left tile, 000, we see that the output is always zero regardless of the input. This is one of the three onefer gates.

Looking at 001, we see that 0 and 1 on the input both results in a zero output, while a 2 on the input results in a 1 output. This is an example of a twofer gate.

Scrolling down and looking at 012, we see a threefer gate, the WIRE gate. A bit further down, we see another threefer gate, the NOT0 gate, ID 021.

These tiles allow me to quickly, graphically evaluate cascades of gates without having to access a lookup table. These have been very valuable for developing insight into the operations of trinary logic.



0_8 Single Input Trinary Gates

  9_17

  18_26

These symbols are available in a zip archive in a DIA shape format at

http://www.kurtnalty.com/TrinaryA.zip

Source code used for this work is included at the end of this file.

Multiplication Table


The traditional next step is to create a multiplication table the logic being studied. The first table is using the 000 style labels, as seen above. This table will be wide.

						Outer Term (Ex: 121(...)  )

000 001 002 010 011 012 020 021 022 100 101 102 110 111 112 120 121 122 200 201 202 210 211 212 220 221 222

000 000 000 000 000 000 000 000 000 000 111 111 111 111 111 111 111 111 111 222 222 222 222 222 222 222 222 222
001 000 000 000 001 001 001 002 002 002 110 110 110 111 111 111 112 112 112 220 220 220 221 221 221 222 222 222
002 000 001 002 000 001 002 000 001 002 110 111 112 110 111 112 110 111 112 220 221 222 220 221 222 220 221 222
010 000 000 000 010 010 010 020 020 020 101 101 101 111 111 111 121 121 121 202 202 202 212 212 212 222 222 222
I 011 000 000 000 011 011 011 022 022 022 100 100 100 111 111 111 122 122 122 200 200 200 211 211 211 222 222 222
N 012 000 001 002 010 011 012 020 021 022 100 101 102 110 111 112 120 121 122 200 201 202 210 211 212 220 221 222
N 020 000 010 020 000 010 020 000 010 020 101 111 121 101 111 121 101 111 121 202 212 222 202 212 222 202 212 222
E 021 000 010 020 001 011 021 002 012 022 100 110 120 101 111 121 102 112 122 200 210 220 201 211 221 202 212 222
R 022 000 011 022 000 011 022 000 011 022 100 111 122 100 111 122 100 111 122 200 211 222 200 211 222 200 211 222
100 000 000 000 100 100 100 200 200 200 011 011 011 111 111 111 211 211 211 022 022 022 122 122 122 222 222 222
T 101 000 000 000 101 101 101 202 202 202 010 010 010 111 111 111 212 212 212 020 020 020 121 121 121 222 222 222
E 102 000 001 002 100 101 102 200 201 202 010 011 012 110 111 112 210 211 212 020 021 022 120 121 122 220 221 222
R 110 000 000 000 110 110 110 220 220 220 001 001 001 111 111 111 221 221 221 002 002 002 112 112 112 222 222 222
M 111 000 000 000 111 111 111 222 222 222 000 000 000 111 111 111 222 222 222 000 000 000 111 111 111 222 222 222
112 000 001 002 110 111 112 220 221 222 000 001 002 110 111 112 220 221 222 000 001 002 110 111 112 220 221 222
120 000 010 020 100 110 120 200 210 220 001 011 021 101 111 121 201 211 221 002 012 022 102 112 122 202 212 222
121 000 010 020 101 111 121 202 212 222 000 010 020 101 111 121 202 212 222 000 010 020 101 111 121 202 212 222
122 000 011 022 100 111 122 200 211 222 000 011 022 100 111 122 200 211 222 000 011 022 100 111 122 200 211 222
200 000 100 200 000 100 200 000 100 200 011 111 211 011 111 211 011 111 211 022 122 222 022 122 222 022 122 222
201 000 100 200 001 101 201 002 102 202 010 110 210 011 111 211 012 112 212 020 120 220 021 121 221 022 122 222
202 000 101 202 000 101 202 000 101 202 010 111 212 010 111 212 010 111 212 020 121 222 020 121 222 020 121 222
210 000 100 200 010 110 210 020 120 220 001 101 201 011 111 211 021 121 221 002 102 202 012 112 212 022 122 222
211 000 100 200 011 111 211 022 122 222 000 100 200 011 111 211 022 122 222 000 100 200 011 111 211 022 122 222
212 000 101 202 010 111 212 020 121 222 000 101 202 010 111 212 020 121 222 000 101 202 010 111 212 020 121 222
220 000 110 220 000 110 220 000 110 220 001 111 221 001 111 221 001 111 221 002 112 222 002 112 222 002 112 222
221 000 110 220 001 111 221 002 112 222 000 110 220 001 111 221 002 112 222 000 110 220 001 111 221 002 112 222
222 000 111 222 000 111 222 000 111 222 000 111 222 000 111 222 000 111 222 000 111 222 000 111 222 000 111 222



A much more compact, yet less informative, table uses A-Z and @ as substitution codes.

000 = A 001 = B 002 = C 010 = D 011 = E 012 = F 020 = G 021 = H 022 = I
100 = J 101 = K 102 = L 110 = M 111 = N 112 = O 120 = P 121 = Q 122 = R
200 = S 201 = T 202 = U 210 = V 211 = W 212 = X 220 = Y 221 = Z 222 = @

Outer Term (Ex: R(...) )

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z @

A A A A A A A A A A N N N N N N N N N @ @ @ @ @ @ @ @ @
B A A A B B B C C C M M M N N N O O O Y Y Y Z Z Z @ @ @
C A B C A B C A B C M N O M N O M N O Y Z @ Y Z @ Y Z @
D A A A D D D G G G K K K N N N Q Q Q U U U X X X @ @ @
E A A A E E E I I I J J J N N N R R R S S S W W W @ @ @
F A B C D E F G H I J K L M N O P Q R S T U V W X Y Z @
G A D G A D G A D G K N Q K N Q K N Q U X @ U X @ U X @
H A D G B E H C F I J M P K N Q L O R S V Y T W Z U X @
I A E I A E I A E I J N R J N R J N R S W @ S W @ S W @
J A A A J J J S S S E E E N N N W W W I I I R R R @ @ @
K A A A K K K U U U D D D N N N X X X G G G Q Q Q @ @ @
L A B C J K L S T U D E F M N O V W X G H I P Q R Y Z @
M A A A M M M Y Y Y B B B N N N Z Z Z C C C O O O @ @ @
N A A A N N N @ @ @ A A A N N N @ @ @ A A A N N N @ @ @
O A B C M N O Y Z @ A B C M N O Y Z @ A B C M N O Y Z @
P A D G J M P S V Y B E H K N Q T W Z C F I L O R U X @
Q A D G K N Q U X @ A D G K N Q U X @ A D G K N Q U X @
R A E I J N R S W @ A E I J N R S W @ A E I J N R S W @
S A J S A J S A J S E N W E N W E N W I R @ I R @ I R @
T A J S B K T C L U D M V E N W F O X G P Y H Q Z I R @
U A K U A K U A K U D N X D N X D N X G Q @ G Q @ G Q @
V A J S D M V G P Y B K T E N W H Q Z C L U F O X I R @
W A J S E N W I R @ A J S E N W I R @ A J S E N W I R @
X A K U D N X G Q @ A K U D N X G Q @ A K U D N X G Q @
Y A M Y A M Y A M Y B N Z B N Z B N Z C O @ C O @ C O @
Z A M Y B N Z C O @ A M Y B N Z C O @ A M Y B N Z C O @
@ A N @ A N @ A N @ A N @ A N @ A N @ A N @ A N @ A N @

When comparing the table to the graphical tiles, there are a few points to keep in mind. The time history of the tiles proceeds left to right, while the usual nesting of arguments in parenthesis goes from innermost parenthesis to outer most terms. As a self-calibration 000(xxx) == 000, and A(x) == A, so the vertical columns are the outer (last in time) arguement. For the example below, 202(100) = 022, and equivalently, U(J) = I.

202_100


Here are the most common, useful gates.

F = WIRE = 012
H = NOT0 = 021
V = NOT1 = 210
L = NOT2 = 102

P = CW   = 120
T = CCW  = 201

Ten of these tiles square to simpler terms. These are great for logic simplification.

HH = VV = LL = F (disappears if not the only term)
BB = GG = AA = A = 000
MM = WW = NN = N = 111
RR = UU = @@ = @ = 222

In additions to WIRE and onefers squaring to themselves, we have the following six self-squares.
CC = C = 002
DD = D = 010
EE = E = 011
II = I = 022
OO = O = 112
XX = X = 212

Illustration of self-projection below for C, D, E, I, O and X.

Squares


The minimum requirements to span this set of gates is quite small. Two distinct inverters and a single twofer, or one inverter, one rotator and one twofer are adequate to span the entire kit. For example, using inverter 102, inverter 021, and twofer 001, we can create or define all 27 elements in this kit.

A commutation map for this logic is shown below. As expected, the squares commute, as does the wire. The onefer gates commute with one third of the function space. The rest of commuters are listed below the table.

       A B C D E F G H I J K L M N O P Q R S T U V W X Y Z @ 

A C C C C C C C C C
B C C C
C C C C C C C
D C C C C C C
E C C C C C C
F C C C C C C C C C C C C C C C C C C C C C C C C C C C
G C C C
H C C C
I C C C C C C
J C C C
K C C C
L C C C
M C C C
N C C C C C C C C C
O C C C C C C
P C C C
Q C C C
R C C C
S C C C
T C C C
U C C C
V C C C
W C C C
X C C C C C C
Y C C C
Z C C C
@ C C C C C C C C C


Commuter pairs (outside the obvious)
C-D   C-Y   D-K   D-N   E-J   E-N   E-O  I-R   I-X    O-Z   P-T  Q-W

002-010   002-220   010-101   010-111   011-100   011-111  
011-112   022-122   022-212   112-221   120-201   121-211

These commutators are potentially useful for simplifying logic by re-arranging product terms to then exploit  the squaring simplifications above.

Each of the gates above can be factored. The most degenerate gates (onefors) have 87 factorizations, while
the twofers each have 24. The threefors have merely six each.


Dual Input Gates

More fun than the 27 single input trinary gates are the 3^9 = 19683 dual input gates. My mental picture of this logic is to treat A as a multiplexer control, selecting one of the three candidate B functions to drive the output. Thinking HIGH, LOW, or TRUE, FALSE is not productive at all in the trinary arena. In my opinion, the three logic levels are equally important, perhaps best thought of as tips on a 120 degree Y shape, rather than as a linear strip.

In binary logic, we had GND, VCC, AND, OR, XOR and XNOR functions which were both associative and commutative. In the trinary world, we have 63 such functions. It is easy to identify three of these functions as our static levels: 0, 9841 and 19682.

This leaves sixty other functions to evaluate for algebraic usefulness. The two that jump out at me as of being of great value are 15665, which matches multiplication for - 0 + symbols, and 14001, which matches modulo 3 addition.

A nice way to group these functions is by permutation family. Treating the logic levels equally, we see that a logic function can be implemented (typically) six different ways. You have three choices for your first logic label, two choices for the second, and no choice at all for the third. As a bit of fine print, for the static levels, once the initial choice is made, as there are no other members, we have no choices, thus only three static levels. Likewise, for the match and rotator functions, the symmetries degenerate (repeat), leaving just three members in those families.

The remaining 54 commutating and associative functions fall neatly into nine permutation familes, and are listed below. What these functions *mean* is a current topic of investigation.

Source code for the tables generated below is at the end of this file.


Both Associative and Commutative

0 9841 19682 - static levels
83 3281 6479 - inputs match
4069 14001 11453 - rotator, mod 3 addition (aka XOR)

1 162 9840 13121 16402 19520
2 81 3280 6560 9842 19601
32 141 4018 4130 9104 14741

112 224 1538 2541 10610 17141
113 143 1619 2543 4019 4049
142 194 3968 4017 8180 15665 Multiplier Family

1536 2460 6673 10609 13346 17222
1617 2462 4048 4100 6674 13265
3168 6336 7381 12301 18146 18914



Static Outputs

0 9841 19682
A B | C A B | C A B | C

0 0 | 0 0 0 | 1 0 0 | 2
0 1 | 0 0 1 | 1 0 1 | 2
0 2 | 0 0 2 | 1 0 2 | 2

1 0 | 0 1 0 | 1 1 0 | 2
1 1 | 0 1 1 | 1 1 1 | 2
1 2 | 0 1 2 | 1 1 2 | 2

2 0 | 0 2 0 | 1 2 0 | 2
2 1 | 0 2 1 | 1 2 1 | 2
2 2 | 0 2 2 | 1 2 2 | 2


Both Inputs Match, and Level

83 3281 6479
A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 0
0 1 | 0 0 1 | 1 0 1 | 2
0 2 | 0 0 2 | 1 0 2 | 2

1 0 | 0 1 0 | 1 1 0 | 2
1 1 | 1 1 1 | 1 1 1 | 1
1 2 | 0 1 2 | 1 1 2 | 2

2 0 | 0 2 0 | 1 2 0 | 2
2 1 | 0 2 1 | 1 2 1 | 2
2 2 | 2 2 2 | 2 2 2 | 2


Rotator - CW, None, CCW

4069 14001 11453 4069 is also a mod 3 adder for 0, 1, 2 tokens
A B | C A B | C A B | C 14001 is also a mod 3 adder for -, 0 , + tokens

0 0 | 0 0 0 | 2 0 0 | 1
0 1 | 1 0 1 | 0 0 1 | 2
0 2 | 2 0 2 | 1 0 2 | 0

1 0 | 1 1 0 | 0 1 0 | 2
1 1 | 2 1 1 | 1 1 1 | 0
1 2 | 0 1 2 | 2 1 2 | 1

2 0 | 2 2 0 | 1 2 0 | 0
2 1 | 0 2 1 | 2 2 1 | 1
2 2 | 1 2 2 | 0 2 2 | 2

**************************************************************

1 162 9840 16402 19520 13121
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 1 0 0 | 2 0 0 | 2 0 0 | 1
0 1 | 0 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 2 0 1 | 2
0 2 | 0 0 2 | 0 0 2 | 1 0 2 | 1 0 2 | 2 0 2 | 2

1 0 | 0 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 2 1 0 | 2
1 1 | 0 1 1 | 2 1 1 | 1 1 1 | 1 1 1 | 0 1 1 | 2
1 2 | 0 1 2 | 0 1 2 | 1 1 2 | 1 1 2 | 2 1 2 | 2

2 0 | 0 2 0 | 0 2 0 | 1 2 0 | 1 2 0 | 2 2 0 | 2
2 1 | 0 2 1 | 0 2 1 | 1 2 1 | 1 2 1 | 2 2 1 | 2
2 2 | 1 2 2 | 0 2 2 | 0 2 2 | 1 2 2 | 2 2 2 | 2



2 81 9842 3280 19601 6560
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 1 0 0 | 0 0 0 | 2 0 0 | 0
0 1 | 0 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 2 0 1 | 2
0 2 | 0 0 2 | 0 0 2 | 1 0 2 | 1 0 2 | 2 0 2 | 2

1 0 | 0 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 2 1 0 | 2
1 1 | 0 1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 2
1 2 | 0 1 2 | 0 1 2 | 1 1 2 | 1 1 2 | 2 1 2 | 2

2 0 | 0 2 0 | 0 2 0 | 1 2 0 | 1 2 0 | 2 2 0 | 2
2 1 | 0 2 1 | 0 2 1 | 1 2 1 | 1 2 1 | 2 2 1 | 2
2 2 | 2 2 2 | 0 2 2 | 2 2 2 | 1 2 2 | 2 2 2 | 2



32 141 9104 4018 14741 4130
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 1 0 0 | 0 0 0 | 2 0 0 | 0
0 1 | 0 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 0 0 1 | 1
0 2 | 0 0 2 | 0 0 2 | 0 0 2 | 2 0 2 | 2 0 2 | 2

1 0 | 0 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 0 1 0 | 1
1 1 | 0 1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 2
1 2 | 1 1 2 | 2 1 2 | 1 1 2 | 1 1 2 | 2 1 2 | 2

2 0 | 0 2 0 | 0 2 0 | 0 2 0 | 2 2 0 | 2 2 0 | 2
2 1 | 1 2 1 | 2 2 1 | 1 2 1 | 1 2 1 | 2 2 1 | 2
2 2 | 2 2 2 | 0 2 2 | 2 2 2 | 1 2 2 | 2 2 2 | 2


112 224 2541 17141 1538 10610
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 2 0 0 | 0 0 0 | 1
0 1 | 0 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 0 0 1 | 1
0 2 | 0 0 2 | 0 0 2 | 0 0 2 | 2 0 2 | 2 0 2 | 2

1 0 | 0 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 0 1 0 | 1
1 1 | 1 1 1 | 2 1 1 | 1 1 1 | 1 1 1 | 0 1 1 | 1
1 2 | 1 1 2 | 2 1 2 | 1 1 2 | 1 1 2 | 2 1 2 | 2

2 0 | 0 2 0 | 0 2 0 | 0 2 0 | 2 2 0 | 2 2 0 | 2
2 1 | 1 2 1 | 2 2 1 | 1 2 1 | 1 2 1 | 2 2 1 | 2
2 2 | 1 2 2 | 2 2 2 | 0 2 2 | 2 2 2 | 2 2 2 | 2



113 143 2543 4019 1619 4049
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 0
0 1 | 0 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 0 0 1 | 1
0 2 | 0 0 2 | 0 0 2 | 0 0 2 | 2 0 2 | 2 0 2 | 2

1 0 | 0 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 0 1 0 | 1
1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 1 1 1 | 1
1 2 | 1 1 2 | 2 1 2 | 1 1 2 | 1 1 2 | 2 1 2 | 2

2 0 | 0 2 0 | 0 2 0 | 0 2 0 | 2 2 0 | 2 2 0 | 2
2 1 | 1 2 1 | 2 2 1 | 1 2 1 | 1 2 1 | 2 2 1 | 2
2 2 | 2 2 2 | 2 2 2 | 2 2 2 | 2 2 2 | 2 2 2 | 2



142 194 4017 15665 3968 8180
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 2 0 0 | 0 0 0 | 1
0 1 | 0 0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 1 0 1 | 0
0 2 | 0 0 2 | 0 0 2 | 2 0 2 | 0 0 2 | 2 0 2 | 2

1 0 | 0 1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 1 1 0 | 0
1 1 | 1 1 1 | 2 1 1 | 1 1 1 | 1 1 1 | 0 1 1 | 1
1 2 | 2 1 2 | 1 1 2 | 1 1 2 | 1 1 2 | 2 1 2 | 2

2 0 | 0 2 0 | 0 2 0 | 2 2 0 | 0 2 0 | 2 2 0 | 2
2 1 | 2 2 1 | 1 2 1 | 1 2 1 | 1 2 1 | 2 2 1 | 2
2 2 | 1 2 2 | 2 2 2 | 0 2 2 | 2 2 2 | 2 2 2 | 2



1536 2460 10609 6673 17222 13346
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 1 0 0 | 1 0 0 | 2 0 0 | 2
0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 0 0 1 | 1 0 1 | 0
0 2 | 2 0 2 | 0 0 2 | 2 0 2 | 0 0 2 | 2 0 2 | 0

1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 0 1 0 | 1 1 0 | 0
1 1 | 0 1 1 | 0 1 1 | 1 1 1 | 1 1 1 | 2 1 1 | 2
1 2 | 2 1 2 | 1 1 2 | 2 1 2 | 1 1 2 | 1 1 2 | 2

2 0 | 2 2 0 | 0 2 0 | 2 2 0 | 0 2 0 | 2 2 0 | 0
2 1 | 2 2 1 | 1 2 1 | 2 2 1 | 1 2 1 | 1 2 1 | 2
2 2 | 0 2 2 | 0 2 2 | 1 2 2 | 1 2 2 | 2 2 2 | 2



1617 2462 4048 6674 4100 13265
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 1 0 0 | 0 0 0 | 2
0 1 | 0 0 1 | 1 0 1 | 1 0 1 | 0 0 1 | 1 0 1 | 0
0 2 | 2 0 2 | 0 0 2 | 2 0 2 | 0 0 2 | 2 0 2 | 0

1 0 | 0 1 0 | 1 1 0 | 1 1 0 | 0 1 0 | 1 1 0 | 0
1 1 | 1 1 1 | 0 1 1 | 1 1 1 | 1 1 1 | 2 1 1 | 1
1 2 | 2 1 2 | 1 1 2 | 2 1 2 | 1 1 2 | 1 1 2 | 2

2 0 | 2 2 0 | 0 2 0 | 2 2 0 | 0 2 0 | 2 2 0 | 0
2 1 | 2 2 1 | 1 2 1 | 2 2 1 | 1 2 1 | 1 2 1 | 2
2 2 | 0 2 2 | 2 2 2 | 1 2 2 | 2 2 2 | 2 2 2 | 2



3168 6336 7381 12301 18146 18914
A B | C A B | C A B | C A B | C A B | C A B | C

0 0 | 0 0 0 | 0 0 0 | 1 0 0 | 1 0 0 | 2 0 0 | 2
0 1 | 1 0 1 | 2 0 1 | 0 0 1 | 2 0 1 | 2 0 1 | 2
0 2 | 1 0 2 | 2 0 2 | 1 0 2 | 1 0 2 | 0 0 2 | 1

1 0 | 1 1 0 | 2 1 0 | 0 1 0 | 2 1 0 | 2 1 0 | 2
1 1 | 0 1 1 | 0 1 1 | 1 1 1 | 1 1 1 | 2 1 1 | 2
1 2 | 0 1 2 | 0 1 2 | 0 1 2 | 2 1 2 | 0 1 2 | 1

2 0 | 1 2 0 | 2 2 0 | 1 2 0 | 1 2 0 | 0 2 0 | 1
2 1 | 0 2 1 | 0 2 1 | 0 2 1 | 2 2 1 | 0 2 1 | 1
2 2 | 0 2 2 | 0 2 2 | 1 2 2 | 1 2 2 | 2 2 2 | 2



Universal Trinary Logic Generation

In binary logic, we can implement any logic function using a handful of standard gates, such as the AND, OR and NOT gates with sum-of-products notation. (Even more simply, we just use NAND gates.) One method of visualizing the process for the two input binary gates is to use the A input as a data selector, gating one of the two single input primitives required for B to the output.

For binary, the second gate is traditionally shown as an OR gate, indicating saturating addition. However, since the process is effectively adding gate B to zeroes, we could implement the addition using an XOR gate, which represents mod 2 addition.

For trinary, we have a similar type of strategy which works. We have three single input triary gates (from our group of 27 earlier) which defined the output pattern for the top, middle and lower output of the truth table. The output of theses three gates feed into three selector functions, S0, S1 and S2, gated by A, which pass data through in their selected state,  but otherwise provide a constant, such as zero. The three selector gates feed into a summer, the output of which is the desired logic. In my illustrations, I will use a mod 3 summer, simply due to personal preference. A traditional summer will work as well, for the selectors which return 0 as the unselected constant.

Generic Trinary Logic Element

First Implementation - Uses Zero Constant Selectors, Mod 3 Adders

  S0         S1         S2              Mod 3 Summer (4069)
A B | C    A B | C    A B | C               A B | C

0 0 | 0    0 0 | 0    0 0 | 0               0 0 | 0
0 1
| 1    0 1 | 0    0 1 | 0               0 1 | 1
0 2 | 2    0 2 | 0    0 2 | 0               0 2 | 2

1 0
| 0    1 0 | 0    1 0 | 0               1 0 | 1
1 1 | 0    1 1 | 1    1 1 | 0               1 1 | 2
1 2 | 0    1 2 | 2    1 2 | 0               1 2 | 0

2 0
| 0    2 0 | 0    2 0 | 0               2 0 | 2
2 1 | 0    2 1 | 0    2 1 | 1               2 1 | 0
2 2 | 0    2 2 | 0    2 2 | 2               2 2 | 1


Second Implementation - Uses 1, 2 Constant Selectors, Mod 3 Adders (1+2 constants sum to zero)

  S0         S1         S2              Mod 3 Summer (4069)
A B | C    A B | C    A B | C               A B | C

0 0 | 0    0 0 | 1    0 0 | 2               0 0 | 0
0 1
| 1    0 1 | 1    0 1 | 2               0 1 | 1
0 2 | 2    0 2 | 1    0 2 | 2               0 2 | 2

1 0
| 1    1 0 | 0    1 0 | 2               1 0 | 1
1 1 | 1    1 1 | 1    1 1 | 2               1 1 | 2
1 2 | 1    1 2 | 2    1 2 | 2               1 2 | 0

2 0
| 1    2 0 | 2    2 0 | 0               2 0 | 2
2 1 | 1    2 1 | 2    2 1 | 1               2 1 | 0
2 2 | 1    2 2 | 2    2 2 | 2               2 2 | 1


Third Implementation - Uses Zero Constant Selectors, Don't Care OR summer

  S0         S1         S2              Mod 3 Summer (4069)
A B | C    A B | C    A B | C               A B | C

0 0 | 0    0 0 | 0    0 0 | 0               0 0 | 0
0 1
| 1    0 1 | 0    0 1 | 0               0 1 | 1
0 2 | 2    0 2 | 0    0 2 | 0               0 2 | 2

1 0
| 0    1 0 | 0    1 0 | 0               1 0 | 1
1 1 | 0    1 1 | 1    1 1 | 0               1 1 | x
1 2 | 0    1 2 | 2    1 2 | 0               1 2 | x

2 0
| 0    2 0 | 0    2 0 | 0               2 0 | 2
2 1 | 0    2 1 | 0    2 1 | 1               2 1 | x
2 2 | 0    2 2 | 0    2 2 | 2               2 2 | x






Trinary Single Gate source code.
Multiplication Tables, Commutators, Factorizations.
#include <stdio.h>


void print(int i)
{
printf("%d",((i/9)%3));
printf("%d",((i/3)%3));
printf("%d",((i)%3));
}

int main(void)
{
int f[27][3]; // single input logic families
int commute[27]; // commutative flag
int i,j,k;
int count;
int a,b,c,A,B,C;
int index;
char letters[27]={"ABCDEFGHIJKLMNOPQRSTUVWXYZ@"};
int onefers[3] = {0, 13, 26};
int twofers[18] = {1, 2, 3, 4, 6, 8, 9, 10, 12, 14, 16, 17, 18, 20, 22, 23, 24, 25};
int threefers[6] = {5, 7, 11, 15, 19, 21};



for (i=0;i<27;i++) {
f[i][2] = i%3; //least significant digit at highest address
f[i][1] = (i/3)%3; // middle
f[i][0] = (i/9)%3; // most significant digit at lowest address
}

// print values for check

for (j=0;j<3;j++) {
printf("%d ",j);
for (i=0;i<27;i++) {
printf("%d ",f[i][j]);
}
printf("\n");
}

// ********************************************************************

// check composite operations

printf("\n\n ");
for (i=0;i<27;i++) {
print(i); printf(" "); //print banner
}
printf("\n\n");

for (i=0;i<27;i++) {
printf(" ");
print(i);
printf(" ");
a = f[i][0]; // inner term
b = f[i][1];
c = f[i][2];
for (j=0;j<27;j++) {
A = f[j][a];
B = f[j][b];
C = f[j][c];
index = C + 3*B + 9*A;
print(index);
printf(" ");
}
printf("\n");
}
printf("\n\n");


// ********************************************************************

// print 000 A, etc as a convenience

printf("\n\n");
for (i=0;i<27;i++) {
if (i%9 == 0) printf("\n");
print(i);
printf(" = %c ",letters[i]);
}
printf("\n");

// check composite operations, print alpha codes

printf("\n\n ");
for (i=0;i<27;i++) {
printf("%c ",letters[i]); //print banner
}
printf("\n\n");

for (i=0;i<27;i++) {
printf("%c ",letters[i]);
printf(" ");
a = f[i][0]; // inner term
b = f[i][1];
c = f[i][2];
for (j=0;j<27;j++) {
A = f[j][a];
B = f[j][b];
C = f[j][c];
index = C + 3*B + 9*A;
printf("%c ",letters[index]);
}
printf("\n");
}
printf("\n\n");






// look at commutator type of relationship

printf("\n\n ");
for (i=0;i<27;i++) {
printf("%c ",letters[i]); //print banner
}
printf("\n\n");

for (i=0;i<27;i++) {
printf("%c ",letters[i]);
printf(" ");
a = f[i][0]; // inner term
b = f[i][1];
c = f[i][2];
for (j=0;j<27;j++) {
A = f[j][f[i][0]] - f[i][f[j][0]];
B = f[j][f[i][1]] - f[i][f[j][1]];
C = f[j][f[i][2]] - f[i][f[j][2]];
if ((A==0) && (B==0) && (C==0)) printf(" C");
else printf(" ");
}
printf("\n");
}
printf("\n\n");


//************************* loop through building factor tables for onefers *****************************



for(k=0;k<3;k++) {
printf("**********************************************\n\nFactors for ");
print(onefers[k]);
printf("\n\n");
count = 0;
for (i=0;i<27;i++) {
a = f[i][0]; // inner term
b = f[i][1];
c = f[i][2];
for (j=0;j<27;j++) {
A = f[j][a];
B = f[j][b];
C = f[j][c];
index = C + 3*B + 9*A;
if (index ==onefers[k]) {
count++;
print(j); printf("("); print(i); printf(") ");
}
}
printf("\n");
}
printf("Count = %d\n\n", count);
}


//************************* loop through building factor tables for twofers *****************************



for(k=0;k<18;k++) {
printf("**********************************************\n\nFactors for ");
print(twofers[k]);
printf("\n\n");
count = 0;
for (i=0;i<27;i++) {
a = f[i][0]; // inner term
b = f[i][1];
c = f[i][2];
for (j=0;j<27;j++) {
A = f[j][a];
B = f[j][b];
C = f[j][c];
index = C + 3*B + 9*A;
if (index ==twofers[k]) {
count++;
print(j); printf("("); print(i); printf(") ");
}
}
printf("\n");
}
printf("Count = %d\n\n", count);
}



//************************* loop through building factor tables for threefers *****************************



for(k=0;k<6;k++) {
printf("**********************************************\n\nFactors for ");
print(threefers[k]);
printf("\n\n");
count = 0;
for (i=0;i<27;i++) {
a = f[i][0]; // inner term
b = f[i][1];
c = f[i][2];
for (j=0;j<27;j++) {
A = f[j][a];
B = f[j][b];
C = f[j][c];
index = C + 3*B + 9*A;
if (index ==threefers[k]) {
count++;
print(j); printf("("); print(i); printf(") ");
}
}
printf("\n");
}
printf("Count = %d\n\n", count);
}


}




Trinary Dual Input Gate source code
#include <stdio.h>

// This program enumerates the 3^9 trinary dual input logic elements


int h[19683][9]; // global array of truth tables
int commutators[729]; // indices for the 729 commutators
int associators[113]; // indices for the 113 associators
int both[63]; // indices for the 63 joint commutators and associators

int print_9(int i)
{
int A, B, C, index, k;

// print this table

printf("\n");
for (k=0;k<9;k++) printf("A B | C ");
printf("\n\n");

for (A=0; A<3; A++) {
for (B=0; B<3; B++) {
index = 3*A + B;
for (k=0;k<9;k++) printf("%d %d | %d ", A, B, h[k+i][index]);
printf("\n");
}
printf("\n");
}
printf("\n");
}



int print9ofboth(int i)
{
int A, B, C, index, k;

// print this table

printf("\n");
for (k=0;k<9;k++) printf(" %5d ",both[k+i]);
printf("\n");
for (k=0;k<9;k++) printf("A B | C ");
printf("\n\n");

for (A=0; A<3; A++) {
for (B=0; B<3; B++) {
index = 3*A + B;
for (k=0;k<9;k++) printf("%d %d | %d ", A, B, h[both[k+i]][index]);
printf("\n");
}
printf("\n");
}
printf("\n");
}


int print_specific_truthtable(int i)
{
int A, B, C, index;

// print this table

printf("\nA B | C\n\n");

for (A=0; A<3; A++) {
for (B=0; B<3; B++) {
index = 3*A + B;
printf("%d %d | %d \n", A, B, h[i][index]);
}
}
printf("\n");
}

int Associative(int i) {

int table[3][3];
int a,b,c,d;
int A,B,C,D;
int j, k, count;

// transcribe the linear 9 long h table into a 3x3 array for clarity

for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
table[A][B] = h[i][3*A + B];
}
}

// generate 27 test cases for (table(A,B),C) =? (table(A,f(B,C))

count = 0;
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
for (C=0;C<3;C++) {
a = table[A][B];
b = table[a][C];
c = table[B][C];
d = table[A][c];
if (b==d) count++;
}
}
}
return (count == 27);
}

void permute(int i) {

int table[3][3];
int permuted_table[3][3];
int p[2]; // permutations. 0 1 2, 0 2 1, 1 0 2, 1 2 0, 2 1 0, 2 0 1
int a,b,c,d;
int A,B,C,D;
int j, k, count;
int local[6][9]; // save local results for printing
int id[6];
int index;

// transcribe the linear 9 long h table into a 3x3 array for clarity

for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
table[A][B] = h[i][3*A + B];
}
}

// *************************

p[0] = 0; p[1] = 1; p[2] = 2; // straight order initially
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
permuted_table[p[A]][p[B]] = p[table[A][B]];
}
}
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
local[0][3*A + B] = permuted_table[A][B];
}
}


p[0] = 0; p[1] = 2; p[2] = 1; // 021
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
permuted_table[p[A]][p[B]] = p[table[A][B]];
}
}
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
local[1][3*A + B] = permuted_table[A][B];
}
}


p[0] = 1; p[1] = 0; p[2] = 2; // 102
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
permuted_table[p[A]][p[B]] = p[table[A][B]];
}
}
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
local[2][3*A + B] = permuted_table[A][B];
}
}


p[0] = 1; p[1] = 2; p[2] = 0; // 120
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
permuted_table[p[A]][p[B]] = p[table[A][B]];
}
}
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
local[3][3*A + B] = permuted_table[A][B];
}
}


p[0] = 2; p[1] = 0; p[2] = 1; // 201
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
permuted_table[p[A]][p[B]] = p[table[A][B]];
}
}
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
local[4][3*A + B] = permuted_table[A][B];
}
}


p[0] = 2; p[1] = 1; p[2] = 0; // 210
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
permuted_table[p[A]][p[B]] = p[table[A][B]];
}
}
for (A=0;A<3;A++) {
for (B=0;B<3;B++) {
local[5][3*A + B] = permuted_table[A][B];
}
}
// ************************

// print and calculate index

for (i=0;i<6;i++) {
id[i] = 0;
for (j=0;j<9;j++) {
id[i] *= 3;
id[i] += local[i][j];
}
}

// ****************************


// print this table

printf("\n");
for (k=0;k<6;k++) printf(" %5d ",id[k]);
printf("\n");
for (k=0;k<6;k++) printf("A B | C ");
printf("\n\n");

for (A=0; A<3; A++) {
for (B=0; B<3; B++) {
index = 3*A + B;
for (k=0;k<6;k++) printf("%d %d | %d ", A, B, local[k][index]);
printf("\n");
}
printf("\n");
}
printf("\n");

}

int main(void)
{
int i,j,k;
int left, right;
int f[3][3], g[3][3]; // local function tables
int a, b, c;
int A, B, C;
int scratch, index, count, linebreaker;
int nassoc, ncommut;


int max_count = 19683; // 3^9 = 19683

for (i=0;i<19683;i++) { //test our array-stuffing algorithm
scratch = i; // do the modulo 3 decomposition on a local copy of the loop variable.
for (j=0;j<9;j++) {
k = 8-j; // make the end of the truth table change the fastest
h[i][k] = scratch % 3; // get least significant trinary digit
scratch /= 3; // divide by three to expose next digit
}
// at this point, h[i,x] should have digits corresponding to truth table column.
}

// print out first fifteen entries

// for (i=0;i<15;i++)
// {
// print_specific_truthtable(i);
// }

// print_9(0);
// print_9(9);
// print_9(18);

// check for commutating logic

printf("\n\nCommutators\n");
linebreaker = 0;
for (i=0;i<19683;i++) {
count = 0;
for (j=0;j<9;j++) {
A = j%3;
B = j/3;
k = 3*A + B; // other index
if (h[i][j] == h[i][k]) count++;
}
if (count == 9) {
if ((linebreaker % 18) == 0) printf("\n");
printf("%5d ",i);
commutators[linebreaker] = i;
linebreaker++;
}

}
printf("\n\nNumber of commutative functions = %d of 19683\n\n",linebreaker);


printf("\n\nAssociators\n");
linebreaker = 0;
for (i=0;i<19683;i++) {
if (Associative(i)) {
if ((linebreaker % 18) == 0) printf("\n");
printf("%5d ",i);
associators[linebreaker] = i;
linebreaker++;
}

}
printf("\n\nNumber of associative functions = %d of 19683\n\n",linebreaker);

// now, report the combined commutator and associator functions.

nassoc = 113;
ncommut = 729;
linebreaker = 0;
printf("\n\nBoth Associative and Commutative\n");
for (i=0;i<nassoc;i++) {
for (j=0;j<ncommut;j++){
if (associators[i] == commutators[j]) {
if ((linebreaker % 18) == 0) printf("\n");
printf("%5d ",associators[i]);
both[linebreaker] = associators[i];
linebreaker++;
}
}
}
printf("\n\nNumber of both associative and commutative functions = %d of 19683\n\n",linebreaker);

// print these out

print9ofboth( 0);
print9ofboth( 9);
print9ofboth(18);
print9ofboth(27);
print9ofboth(36);
print9ofboth(45);
print9ofboth(54);

permute(1);
permute(2);
permute(32);
permute(83);
permute(112);
permute(113);
permute(142);
permute(1536);
permute(1617);
permute(3168);
permute(4069);



}