-
Notifications
You must be signed in to change notification settings - Fork 0
/
ternary.go
210 lines (187 loc) · 4.66 KB
/
ternary.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// Package ternary is a Go library to calculate three-valued logic.
//
// This package is based on Kleene's strong logic of indeterminacy.
// Ternary has three truth values, TRUE, FALSE and UNKNOWN.
//
// Numeric representation of truth values
/*
FALSE: -1
UNKNOWN: 0
TRUE: 1
*/
//
// Truth tables
/*
NOT(A) - Logical negation
+---+----+
| A | ¬A |
|---+----|
| F | T |
| U | U |
| T | F |
+---+----+
AND(A, B) - Logical conjunction. Minimum value of (A, B)
+--------+-----------|
| | B |
| A ∧ B |---+---+---|
| | F | U | T |
|----+---+---+---+---|
| | F | F | F | F |
| A | U | F | U | U |
| | T | F | U | T |
+----+---+---+---+---+
OR(A, B) - Logical disjunction. Maximum value of (A, B)
+--------+-----------+
| | B |
| A ∨ B |---+---+---|
| | F | U | T |
|----+---+---+---+---|
| | F | F | U | T |
| A | U | U | U | T |
| | T | T | T | T |
+----+---+---+---+---+
IMP(A, B) - Logical implication. OR(NOT(A), B)
+--------+-----------+
| | B |
| A → B |---+---+---|
| | F | U | T |
|----+---+---+---+---|
| | F | T | T | T |
| A | U | U | U | T |
| | T | F | U | T |
+----+---+---+---+---+
EQV(A, B) - Logical biconditional. OR(AND(A, B), AND(NOT(A), NOT(B)))
+--------+-----------+
| | B |
| A ↔ B |---+---+---|
| | F | U | T |
|----+---+---+---+---|
| | F | T | U | F |
| A | U | U | U | U |
| | T | F | U | T |
+----+---+---+---+---+
*/
package ternary
import (
"errors"
"fmt"
"reflect"
"strings"
)
// Value represents a truth value
type Value int8
const (
FALSE Value = iota - 1
UNKNOWN
TRUE
)
var literals = map[Value]string{
FALSE: "FALSE",
UNKNOWN: "UNKNOWN",
TRUE: "TRUE",
}
// String returns string representation of the value.
func (value Value) String() string {
return literals[value]
}
// Int returns integer representation of the value.
func (value Value) Int() int64 {
return reflect.ValueOf(value).Int()
}
// ParseBool returns true if the value is TRUE, otherwise returns false.
func (value Value) ParseBool() bool {
if value != TRUE {
return false
}
return true
}
// ConvertFromString converts a string to a ternary value.
// If the string is any of "false", "FALSE" and "-1", then it is converted to FALSE.
// If the string is any of "unknown", "UNKNOWN" and "0", then it is converted to UNKNOWN.
// If the string is any of "true", "TRUE" and "1", then it is converted to TRUE.
// Otherwise, returns an error.
func ConvertFromString(s string) (Value, error) {
switch strings.ToUpper(s) {
case literals[FALSE], "-1":
return FALSE, nil
case literals[TRUE], "1":
return TRUE, nil
case literals[UNKNOWN], "0":
return UNKNOWN, nil
}
return UNKNOWN, errors.New(fmt.Sprintf("convert from %q: invalid value", s))
}
// ConvertFromInt64 converts an integer to a ternary value.
// Returns FALSE if the integer is -1, returns UNKNOWN if it is 0, and returns TRUE if it is 1.
// Otherwise, returns an error.
func ConvertFromInt64(i int64) (Value, error) {
switch i {
case -1:
return FALSE, nil
case 0:
return UNKNOWN, nil
case 1:
return TRUE, nil
}
return UNKNOWN, errors.New(fmt.Sprintf("convert from %d: invalid value", i))
}
// ConvertFromBool converts a boolean to a ternary value.
// Returns FALSE if the boolean is false, returns TRUE if it is true.
func ConvertFromBool(b bool) Value {
if b {
return TRUE
}
return FALSE
}
// Equal checks if two values are the same value, not logical equality.
func Equal(a Value, b Value) Value {
return ConvertFromBool(a == b)
}
// Not returns the result of logical negation for a value.
func Not(a Value) Value {
return a * -1
}
// And returns the result of logical conjunction for two values.
func And(a Value, b Value) Value {
if a < b {
return a
}
return b
}
// Or returns the result of logical disjunction for two values.
func Or(a Value, b Value) Value {
if a > b {
return a
}
return b
}
// Imp returns the result of logical implication that is represented as "a implies b".
func Imp(a Value, b Value) Value {
return Or(Not(a), b)
}
// Eqv returns the result of logical biconditional for two values.
func Eqv(a Value, b Value) Value {
return a * b
}
// All returns the result of logical conjunction on all values.
func All(values []Value) Value {
t := TRUE
for i := 0; i < len(values); i++ {
t = And(t, values[i])
if t == FALSE {
return FALSE
}
}
return t
}
// Any returns the result of logical disjunction on all values.
func Any(values []Value) Value {
t := FALSE
for i := 0; i < len(values); i++ {
t = Or(t, values[i])
if t == TRUE {
return TRUE
}
}
return t
}