forked from johnkerl/miller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mlrval_cmp.go
162 lines (143 loc) · 5.3 KB
/
mlrval_cmp.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
// ================================================================
// Boolean expressions for ==, !=, >, >=, <, <=, <=> on Mlrvals.
//
// Note that in bifs/boolean.go we have similar functions which take pairs of
// Mlrvals as input and return Mlrval as output. Those are for use in the
// Miller DSL. The functions here are primarily for 'mlr sort'. Their benefit
// is they don't allocate memory, and so are more efficient for sort we don't
// want to trigger lots of allocations, nor garbage collection, if we can avoid
// it.
// ================================================================
// TODO: comment about mvtype; deferral; copying of deferrence.
package mlrval
import (
"github.com/johnkerl/miller/internal/pkg/lib"
)
type CmpFuncBool func(input1, input2 *Mlrval) bool
// The Go sort API is just a bool a<b, not triple a<b, a==b, a>b. Miller does the latter since when
// we sort primarily on field 1, then secondarily on field 2, etc., we need to be able to detect
// ties on field 1 so we can know whether to compare on field 2 or not.
type CmpFuncInt func(input1, input2 *Mlrval) int // -1, 0, 1 for <=>
// ----------------------------------------------------------------
// Exported methods
func Equals(input1, input2 *Mlrval) bool {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) == 0
}
func NotEquals(input1, input2 *Mlrval) bool {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) != 0
}
func GreaterThan(input1, input2 *Mlrval) bool {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) > 0
}
func GreaterThanOrEquals(input1, input2 *Mlrval) bool {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) >= 0
}
func LessThan(input1, input2 *Mlrval) bool {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) < 0
}
func LessThanOrEquals(input1, input2 *Mlrval) bool {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2) <= 0
}
func Cmp(input1, input2 *Mlrval) int {
return cmp_dispositions[input1.Type()][input2.Type()](input1, input2)
}
// ----------------------------------------------------------------
// Support routines for disposition-matrix entries
// _same returns int 0 as a binary-input function
func _same(input1, input2 *Mlrval) int {
return 0
}
// _less returns int -1 as a binary-input function
func _less(input1, input2 *Mlrval) int {
return -1
}
// _more returns int 1 as a binary-input function
func _more(input1, input2 *Mlrval) int {
return 1
}
// int_cmp implements the spaceship operator for ints.
func int_cmp(a, b int64) int {
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
// float_cmp implements the spaceship operator for floats.
func float_cmp(a, b float64) int {
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
// string_cmp implements the spaceship operator for strings.
func string_cmp(a, b string) int {
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
// ----------------------------------------------------------------
// Disposition-matrix entries
func cmp_b_ss(input1, input2 *Mlrval) int {
return string_cmp(input1.printrep, input2.printrep)
}
func cmp_b_ii(input1, input2 *Mlrval) int {
return int_cmp(input1.intval, input2.intval)
}
func cmp_b_if(input1, input2 *Mlrval) int {
return float_cmp(float64(input1.intval), input2.floatval)
}
func cmp_b_fi(input1, input2 *Mlrval) int {
return float_cmp(input1.floatval, float64(input2.intval))
}
func cmp_b_ff(input1, input2 *Mlrval) int {
return float_cmp(input1.floatval, input2.floatval)
}
func cmp_b_bb(input1, input2 *Mlrval) int {
return int_cmp(int64(lib.BoolToInt(input1.boolval)), int64(lib.BoolToInt(input2.boolval)))
}
// TODO: cmp on array & map
//func eq_b_aa(input1, input2 *Mlrval) bool {
// a := input1.arrayval
// b := input2.arrayval
//
// // Different-length arrays are not equal
// if len(a) != len(b) {
// return false
// }
//
// // Same-length arrays: return false if any slot is not equal, else true.
// for i := range a {
// if !Equals(&a[i], &b[i]) {
// return false
// }
// }
//
// return true
//}
//func eq_b_mm(input1, input2 *Mlrval) bool {
// return input1.mapval.Equals(input2.mapval)
//}
var cmp_dispositions = [MT_DIM][MT_DIM]CmpFuncInt{
// . INT FLOAT BOOL VOID STRING ARRAY MAP FUNC ERROR NULL ABSENT
/*INT */ {cmp_b_ii, cmp_b_if, _less, _less, _less, _less, _less, _less, _less, _less, _less},
/*FLOAT */ {cmp_b_fi, cmp_b_ff, _less, _less, _less, _less, _less, _less, _less, _less, _less},
/*BOOL */ {_more, _more, cmp_b_bb, _less, _less, _less, _less, _less, _less, _less, _less},
/*VOID */ {_more, _more, _more, cmp_b_ss, cmp_b_ss, _less, _less, _less, _less, _less, _less},
/*STRING */ {_more, _more, _more, cmp_b_ss, cmp_b_ss, _less, _less, _less, _less, _less, _less},
/*ARRAY */ {_more, _more, _more, _more, _more, _same, _less, _less, _less, _less, _less},
/*MAP */ {_more, _more, _more, _more, _more, _more, _same, _less, _less, _less, _less},
/*func */ {_more, _more, _more, _more, _more, _more, _more, _same, _less, _less, _less},
/*ERROR */ {_more, _more, _more, _more, _more, _more, _more, _more, _same, _less, _less},
/*NULL */ {_more, _more, _more, _more, _more, _more, _more, _more, _more, _same, _less},
/*ABSENT */ {_more, _more, _more, _more, _more, _more, _more, _more, _more, _more, _same},
}