10
10
import java .io .UncheckedIOException ;
11
11
import java .io .Writer ;
12
12
import java .nio .charset .StandardCharsets ;
13
+ import java .util .Arrays ;
13
14
import java .util .function .Consumer ;
14
15
import software .amazon .smithy .rulesengine .logic .ConditionEvaluator ;
15
16
@@ -36,9 +37,7 @@ public final class Bdd {
36
37
*/
37
38
public static final int RESULT_OFFSET = 100_000_000 ;
38
39
39
- private final int [] variables ;
40
- private final int [] highs ;
41
- private final int [] lows ;
40
+ private final int [] nodes ; // Flat array: [var0, high0, low0, var1, high1, low1, ...]
42
41
private final int rootRef ;
43
42
private final int conditionCount ;
44
43
private final int resultCount ;
@@ -64,27 +63,29 @@ public Bdd(int rootRef, int conditionCount, int resultCount, int nodeCount, Cons
64
63
65
64
InputNodeConsumer consumer = new InputNodeConsumer (nodeCount );
66
65
nodeHandler .accept (consumer );
67
- this .variables = consumer .variables ;
68
- this .highs = consumer .highs ;
69
- this .lows = consumer .lows ;
66
+ this .nodes = consumer .nodes ;
70
67
71
- if (consumer .index != nodeCount ) {
72
- throw new IllegalStateException ("Expected " + nodeCount + " nodes, but got " + consumer .index );
68
+ if (consumer .index != nodeCount * 3 ) {
69
+ throw new IllegalStateException ("Expected " + nodeCount + " nodes, but got " + ( consumer .index / 3 ) );
73
70
}
74
71
}
75
72
76
- Bdd (int [] variables , int [] highs , int [] lows , int nodeCount , int rootRef , int conditionCount , int resultCount ) {
77
- validateArrays (variables , highs , lows , nodeCount );
73
+ /**
74
+ * Package-private constructor for direct array initialization (used by BddTrait).
75
+ */
76
+ Bdd (int rootRef , int conditionCount , int resultCount , int nodeCount , int [] nodes ) {
78
77
validateCounts (conditionCount , resultCount , nodeCount );
79
78
validateRootReference (rootRef , nodeCount );
80
79
81
- this .variables = variables ;
82
- this .highs = highs ;
83
- this .lows = lows ;
80
+ if (nodes .length != nodeCount * 3 ) {
81
+ throw new IllegalArgumentException ("Nodes array length must be nodeCount * 3" );
82
+ }
83
+
84
84
this .rootRef = rootRef ;
85
85
this .conditionCount = conditionCount ;
86
86
this .resultCount = resultCount ;
87
87
this .nodeCount = nodeCount ;
88
+ this .nodes = nodes ;
88
89
}
89
90
90
91
private static void validateCounts (int conditionCount , int resultCount , int nodeCount ) {
@@ -109,34 +110,19 @@ private static void validateRootReference(int rootRef, int nodeCount) {
109
110
}
110
111
}
111
112
112
- private static void validateArrays (int [] variables , int [] highs , int [] lows , int nodeCount ) {
113
- if (variables .length != highs .length || variables .length != lows .length ) {
114
- throw new IllegalArgumentException ("Array lengths must match: variables=" + variables .length +
115
- ", highs=" + highs .length + ", lows=" + lows .length );
116
- } else if (nodeCount > variables .length ) {
117
- throw new IllegalArgumentException ("Node count (" + nodeCount +
118
- ") exceeds array capacity (" + variables .length + ")" );
119
- }
120
- }
121
-
122
113
private static final class InputNodeConsumer implements BddNodeConsumer {
123
114
private int index = 0 ;
124
- private final int [] variables ;
125
- private final int [] highs ;
126
- private final int [] lows ;
115
+ private final int [] nodes ;
127
116
128
117
private InputNodeConsumer (int nodeCount ) {
129
- this .variables = new int [nodeCount ];
130
- this .highs = new int [nodeCount ];
131
- this .lows = new int [nodeCount ];
118
+ this .nodes = new int [nodeCount * 3 ];
132
119
}
133
120
134
121
@ Override
135
122
public void accept (int var , int high , int low ) {
136
- variables [index ] = var ;
137
- highs [index ] = high ;
138
- lows [index ] = low ;
139
- index ++;
123
+ nodes [index ++] = var ;
124
+ nodes [index ++] = high ;
125
+ nodes [index ++] = low ;
140
126
}
141
127
}
142
128
@@ -184,7 +170,7 @@ public int getRootRef() {
184
170
*/
185
171
public int getVariable (int nodeIndex ) {
186
172
validateRange (nodeIndex );
187
- return variables [nodeIndex ];
173
+ return nodes [nodeIndex * 3 ];
188
174
}
189
175
190
176
private void validateRange (int index ) {
@@ -201,7 +187,7 @@ private void validateRange(int index) {
201
187
*/
202
188
public int getHigh (int nodeIndex ) {
203
189
validateRange (nodeIndex );
204
- return highs [nodeIndex ];
190
+ return nodes [nodeIndex * 3 + 1 ];
205
191
}
206
192
207
193
/**
@@ -212,7 +198,7 @@ public int getHigh(int nodeIndex) {
212
198
*/
213
199
public int getLow (int nodeIndex ) {
214
200
validateRange (nodeIndex );
215
- return lows [nodeIndex ];
201
+ return nodes [nodeIndex * 3 + 2 ];
216
202
}
217
203
218
204
/**
@@ -222,7 +208,8 @@ public int getLow(int nodeIndex) {
222
208
*/
223
209
public void getNodes (BddNodeConsumer consumer ) {
224
210
for (int i = 0 ; i < nodeCount ; i ++) {
225
- consumer .accept (variables [i ], highs [i ], lows [i ]);
211
+ int base = i * 3 ;
212
+ consumer .accept (nodes [base ], nodes [base + 1 ], nodes [base + 2 ]);
226
213
}
227
214
}
228
215
@@ -234,14 +221,13 @@ public void getNodes(BddNodeConsumer consumer) {
234
221
*/
235
222
public int evaluate (ConditionEvaluator ev ) {
236
223
int ref = rootRef ;
237
- int [] vars = this .variables ;
238
- int [] hi = this .highs ;
239
- int [] lo = this .lows ;
224
+ int [] n = this .nodes ;
240
225
241
226
while (isNodeReference (ref )) {
242
- int idx = ref > 0 ? ref - 1 : -ref - 1 ; // Math.abs
227
+ int idx = ref > 0 ? ref - 1 : -ref - 1 ;
228
+ int base = idx * 3 ;
243
229
// test ^ complement, pick hi or lo
244
- ref = (ev .test (vars [ idx ]) ^ (ref < 0 )) ? hi [ idx ] : lo [ idx ];
230
+ ref = (ev .test (n [ base ]) ^ (ref < 0 )) ? n [ base + 1 ] : n [ base + 2 ];
245
231
}
246
232
247
233
return isTerminal (ref ) ? -1 : ref - RESULT_OFFSET ;
@@ -303,27 +289,12 @@ public boolean equals(Object obj) {
303
289
return false ;
304
290
}
305
291
306
- // Now check the views of arrays of each.
307
- for (int i = 0 ; i < nodeCount ; i ++) {
308
- if (variables [i ] != other .variables [i ] || highs [i ] != other .highs [i ] || lows [i ] != other .lows [i ]) {
309
- return false ;
310
- }
311
- }
312
-
313
- return true ;
292
+ return Arrays .equals (nodes , other .nodes );
314
293
}
315
294
316
295
@ Override
317
296
public int hashCode () {
318
- int hash = 31 * rootRef + nodeCount ;
319
- // Sample up to 16 nodes distributed across the BDD
320
- int step = Math .max (1 , nodeCount / 16 );
321
- for (int i = 0 ; i < nodeCount ; i += step ) {
322
- hash = 31 * hash + variables [i ];
323
- hash = 31 * hash + highs [i ];
324
- hash = 31 * hash + lows [i ];
325
- }
326
- return hash ;
297
+ return 31 * rootRef + nodeCount + Arrays .hashCode (nodes );
327
298
}
328
299
329
300
@ Override
0 commit comments