-
Notifications
You must be signed in to change notification settings - Fork 54
/
QuantBody.java.jpp
2351 lines (2193 loc) · 62.8 KB
/
QuantBody.java.jpp
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#if 0
Do not attempt to compile this file with a Java compiler such as javac.
You first need to preprocess it with cpp, the C preprocessor.
The correct way to build the system is to run 'make'.
#endif
#if !(defined(BOOLEAN) \
|| defined(BYTE) \
|| defined(CHAR) \
|| defined(DOUBLE) \
|| defined(FLOAT) \
|| defined(INT) \
|| defined(LONG) \
|| defined(SHORT) \
|| defined(OBJECT) \
|| defined(STRING))
#error "One of BOOLEAN, BYTE, CHAR, DOUBLE, FLOAT, INT, INTEGER, LONG, SHORT, OBJECT, STRING must be defined"
#endif
#undef _TYPE
#undef _TYPE_ARG
#undef _TYPE_NAME
#undef _TYPE_WRAPPER_NAME
#undef _TYPE_ARG
#define _TYPE_ARG
#undef ARRAY_GET_NAME
#undef BAD_VALUE
#undef BAD_VALUE_QUALIFIER
#define BAD_VALUE_QUALIFIER
#if defined(BOOLEAN)
#define _TYPE boolean
#define _TYPE_NAME boolean
#define _TYPE_WRAPPER_NAME Boolean
#define BAD_VALUE false
#elif defined(BYTE)
#define _TYPE byte
#define _TYPE_NAME byte
#define _TYPE_WRAPPER_NAME Byte
#define BAD_VALUE Byte.MAX_VALUE
#elif defined(CHAR)
#define _TYPE char
#define _TYPE_NAME char
#define _TYPE_WRAPPER_NAME Character
#define BAD_VALUE Character.MAX_VALUE
#elif defined(DOUBLE)
#define _TYPE double
#define _TYPE_NAME double
#define _TYPE_WRAPPER_NAME Double
#define BAD_VALUE Double.NaN
#elif defined(FLOAT)
#define _TYPE float
#define _TYPE_NAME float
#define _TYPE_WRAPPER_NAME Float
#define BAD_VALUE Float.NaN
#elif defined(INT)
#define _TYPE int
#define _TYPE_NAME int
#define _TYPE_WRAPPER_NAME Integer
#define BAD_VALUE Integer.MAX_VALUE
#elif defined(LONG)
#define _TYPE long
#define _TYPE_NAME long
#define _TYPE_WRAPPER_NAME Long
#define BAD_VALUE Long.MAX_VALUE
#elif defined(SHORT)
#define _TYPE short
#define _TYPE_NAME short
#define _TYPE_WRAPPER_NAME Short
#define BAD_VALUE Short.MAX_VALUE
#elif defined(OBJECT)
#define _TYPE @Interned Object
#define _TYPE_NAME Object
#undef _TYPE_ARG
#define _TYPE_ARG <@Interned Object>
#define BAD_VALUE null
#undef BAD_VALUE_QUALIFIER
#define BAD_VALUE_QUALIFIER @Nullable
#elif defined(STRING)
#define _TYPE @Interned String
#define _TYPE_NAME String
#undef _TYPE_ARG
#define _TYPE_ARG <@Interned String>
#define BAD_VALUE null
#undef BAD_VALUE_QUALIFIER
#define BAD_VALUE_QUALIFIER @Nullable
#endif
#if defined(OBJECT)
#define GETVALUE(object) object
#elif defined(STRING)
#define GETVALUE(object) (String)object
#else
#define GETVALUE(object) ((_TYPE_WRAPPER_NAME)fieldObj)._TYPE_NAME ## Value()
#endif
#undef ARRAY_GET_NAME
#if defined(OBJECT)
#define ARRAY_GET_NAME java.lang.reflect.Array.get
#elif defined(STRING)
#define ARRAY_GET_NAME (String)java.lang.reflect.Array.get
#elif defined(CHAR)
#define ARRAY_GET_NAME java.lang.reflect.Array.getChar
#elif defined(INT)
#define ARRAY_GET_NAME java.lang.reflect.Array.getInt
#else
#define ARRAY_GET_NAME ARRAY_GET_NAME2(_TYPE_WRAPPER_NAME)
#define ARRAY_GET_NAME2(TYPEWRAPPERNAME) java.lang.reflect.Array.get ## TYPEWRAPPERNAME
#endif
#if 0
For an explanation of the indirection, see
http://stackoverflow.com/questions/8231966/why-do-i-need-double-layer-of-indirection-for-macros
#endif
#define COLLECT_TYPE COLLECT_TYPE2(_TYPE_NAME)
#define COLLECT_TYPE2(TYPENAME) collect ## TYPENAME
#define COLLECT_TYPE_FIELD COLLECT_TYPE_FIELD2(_TYPE_NAME)
#define COLLECT_TYPE_FIELD2(TYPENAME) collect ## TYPENAME ## _field
#define GET_ELEMENT GET_ELEMENT2(_TYPE_NAME)
#define GET_ELEMENT2(TYPENAME) getElement_ ## TYPENAME
#if 0
This file gets included multiple times, so it is crucial to undefine
any macro that might not be defined on every path.
#endif
#undef COMPATIBLE
#undef CAST_TYPE
#if 0
CAST_TYPE is different than either COMPATIBLE or _TYPE. This tells which.
#endif
#undef CAST_TYPE_IS_DIFFERENT_THAN_COMPATIBLE
#if defined(BYTE)
#define COMPATIBLE int
#define CAST_TYPE int
#endif
#if defined(INT)
#define COMPATIBLE long
#define CAST_TYPE long
#endif
#if defined(LONG)
#define COMPATIBLE int
#define CAST_TYPE long
#define CAST_TYPE_IS_DIFFERENT_THAN_COMPATIBLE 1
#endif
#if defined(DOUBLE)
#define COMPATIBLE float
#define CAST_TYPE double
#define CAST_TYPE_IS_DIFFERENT_THAN_COMPATIBLE 1
#endif
#if defined(FLOAT)
#define COMPATIBLE double
#define CAST_TYPE double
#endif
#undef NUMERIC
#if defined(COMPATIBLE) || defined(SHORT) || defined(CHAR)
#define NUMERIC
#endif
///////////////////////////////////////////////////////////////////////////
/// Methods for #_TYPE (from QuantBody.java.jpp)
///
/**
* Returns the ith element of the array or collection argument. If the argument is null or not an
* array or collection, returns a default value (BAD_VALUE).
*/
#if defined(OBJECT) || defined(STRING)
@SuppressWarnings("interning") // reflection
#endif
#if defined(BOOLEAN)
@EnsuresNonNullIf(result=true, expression="#1")
#endif
@Pure
public static BAD_VALUE_QUALIFIER _TYPE GET_ELEMENT(Object o, long i) {
if (o == null) {
return BAD_VALUE; // return default value
}
java.lang.Class<?> c = o.getClass();
if (c.isArray()) {
return ARRAY_GET_NAME(o, (int)i);
} else if (o instanceof java.util.AbstractCollection<?>) {
return ARRAY_GET_NAME(((java.util.AbstractCollection<?>)o).toArray(), (int)i);
} else {
return BAD_VALUE; // return default value
}
}
#if defined(OBJECT) || defined(STRING)
@SuppressWarnings("interning") // called reflectively
#endif
#if defined(BOOLEAN)
@EnsuresNonNullIf(result=true, expression="#1")
#endif
@Pure
public static BAD_VALUE_QUALIFIER _TYPE GET_ELEMENT(_TYPE_NAME[] arr, long i) {
if (arr == null) {
return BAD_VALUE; // return default value
}
return arr[(int)i];
}
#if (defined(FLOAT) || defined(DOUBLE))
private static boolean eq(_TYPE x, _TYPE y) {
return fuzzy.eq(x,y);
}
private static boolean ne(_TYPE x, _TYPE y) {
return fuzzy.ne(x,y);
}
#if !(defined(BOOLEAN) || defined(OBJECT) || defined(STRING))
private static boolean lt(_TYPE x, _TYPE y) {
return fuzzy.lt(x,y);
}
private static boolean lte(_TYPE x, _TYPE y) {
return fuzzy.lte(x,y);
}
private static boolean gt(_TYPE x, _TYPE y) {
return fuzzy.gt(x,y);
}
private static boolean gte(_TYPE x, _TYPE y) {
return fuzzy.gte(x,y);
}
#endif
#else
private static boolean eq(_TYPE x, _TYPE y) {
return (x == y);
}
private static boolean ne(_TYPE x, _TYPE y) {
return x != y;
}
#if !(defined(BOOLEAN) || defined(OBJECT) || defined(STRING))
private static boolean lt(_TYPE x, _TYPE y) {
return x < y;
}
private static boolean lte(_TYPE x, _TYPE y) {
return x <= y;
}
private static boolean gt(_TYPE x, _TYPE y) {
return x > y;
}
private static boolean gte(_TYPE x, _TYPE y) {
return x >= y;
}
#endif
#endif /* (defined(FLOAT) || defined(DOUBLE)) */
#if (defined(OBJECT))
/**
* Returns an array of Strings, where the strings are the result of invoking
* x.getClass().toString() for each element x in the array. If an element of the array is null,
* its slot in the returned array is null.
*/
@SideEffectFree
public static @PolyNull/*("elt")*/ String @PolyNull/*("container")*/ [] typeArray(@PolyNull/*("elt")*/ _TYPE @PolyNull/*("container")*/ [] seq) {
if (seq == null) {
return null;
}
@PolyNull/*("elt")*/ String[] retval = new @PolyNull/*("elt")*/ String[seq.length];
for (int i = 0 ; i < seq.length ; i++) {
if (seq[i] == null) {
retval[i] = null;
} else {
retval[i] = seq[i].getClass().toString();
}
}
return retval;
}
#endif
/** True iff both sequences are non-null and have the same length. */
@EnsuresNonNullIf(result=true, expression={"#1", "#2"})
@Pure
public static boolean sameLength(_TYPE_NAME @Nullable [] seq1, _TYPE_NAME @Nullable [] seq2) {
return ((seq1 != null)
&& (seq2 != null)
&& seq1.length == seq2.length);
}
#ifdef COMPATIBLE
/** True iff both sequences are non-null and have the same length. */
@EnsuresNonNullIf(result=true, expression={"#1", "#2"})
@Pure
public static boolean sameLength(_TYPE_NAME @Nullable [] seq1, COMPATIBLE @Nullable [] seq2) {
return ((seq1 != null)
&& (seq2 != null)
&& seq1.length == seq2.length);
}
#endif
#if (defined(BYTE) || defined(INT) || defined(LONG) || defined(FLOAT) || defined(DOUBLE))
/** True iff both sequences have the same length, and all seq2[i] divide seq1[i].
*
* Meaning (in pseudo-FOL):
*
* <pre>
* /\ seq1.length == seq2.length
* /\ forall i in { 0..seq2.length-1 } : seq2[i] divides seq1[i]
* </pre>
*
*/
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseDivides(_TYPE[] seq1, _TYPE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
if (ne(seq1[i] % seq2[i], 0)) {
return false;
}
}
return true;
}
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseDivides(_TYPE[] seq1, COMPATIBLE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
if (ne(seq1[i] % seq2[i], 0)) {
return false;
}
}
return true;
}
/**
* True iff both sequences have the same length, and all seq1[i] == seq2[i] * seq2[i].
*
* Meaning (in pseudo-FOL):
*
* <pre>
* /\ seq1.length == seq2.length
* /\ forall i in { 0..seq2.length-1 } : seq1[i] == seq2[i] * seq2[i]
* </pre>
*
*/
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseSquare(_TYPE[] seq1, _TYPE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
if (ne(seq1[i], seq2[i] * seq2[i])) {
return false;
}
}
return true;
}
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseSquare(_TYPE[] seq1, COMPATIBLE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
#if defined(CAST_TYPE_IS_DIFFERENT_THAN_COMPATIBLE)
if (ne(seq1[i], ((CAST_TYPE) seq2[i]) * ((CAST_TYPE) seq2[i]))) {
#else
if (ne(seq1[i], seq2[i] * seq2[i])) {
#endif
return false;
}
}
return true;
}
#endif
#if (defined(INT) || defined(LONG))
/** True iff both sequences have the same length, and all seq1[i] == ~ seq2[i].
*
* Meaning (in pseudo-FOL):
*
* <pre>
* /\ seq1.length == seq2.length
* /\ forall i in { 0..seq2.length-1 } : seq1[i] == ~ seq2[i]
* </pre>
*
*/
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseBitwiseComplement(_TYPE[] seq1, _TYPE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
if (seq1[i] != ~seq2[i]) {
return false;
}
}
return true;
}
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseBitwiseComplement(_TYPE[] seq1, COMPATIBLE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
if (seq1[i] != ~seq2[i]) {
return false;
}
}
return true;
}
#if 0
This has nothing to do with INT.
The test ensures that the method only appears once in the output.
#endif
#if (defined(INT))
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseBitwiseComplement(Object[] seq1, Object[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
if (!eltsNonNull(seq1)) {
return false;
}
if (!eltsNonNull(seq2)) {
return false;
}
int[] hashArr1 = new int[seq1.length];
for (int i = 0 ; i < seq1.length ; i++) {
hashArr1[i] = seq1[i].hashCode();
}
int[] hashArr2 = new int[seq2.length];
for (int i = 0 ; i < seq2.length ; i++) {
hashArr2[i] = seq2[i].hashCode();
}
return pairwiseBitwiseComplement(hashArr1, hashArr2);
}
#endif
/** True iff both sequences have the same length, and all seq1[i] == (seq2[i] | seq1[i]).
*
* Meaning (in pseudo-FOL):
*
* <pre>
* /\ seq1.length == seq2.length
* /\ forall i in { 0..seq2.length-1 } : seq1[i] == (seq2[i] | seq1[i])
* </pre>
*
*/
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseBitwiseSubset(_TYPE[] seq1, _TYPE[] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
if (seq1.length != seq2.length) {
return false;
}
for (int i = 0 ; i < seq1.length ; i++) {
if (ne(seq1[i], (seq2[i] | seq1[i]))) {
return false;
}
}
return true;
}
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseBitwiseSubset(_TYPE[] seq1, COMPATIBLE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
for (int i = 0 ; i < seq1.length ; i++) {
if (ne(seq1[i], (seq2[i] | seq1[i]))) {
return false;
}
}
return true;
}
#if 0
This has nothing to do with INT.
The test ensures that the method only appears once in the output.
#endif
#if (defined(INT))
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean pairwiseBitwiseSubset(Object[] seq1, Object[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
if (!eltsNonNull(seq1)) {
return false;
}
if (!eltsNonNull(seq2)) {
return false;
}
int[] hashArr1 = new int[seq1.length];
for (int i = 0 ; i < seq1.length ; i++) {
hashArr1[i] = seq1[i].hashCode();
}
int[] hashArr2 = new int[seq2.length];
for (int i = 0 ; i < seq2.length ; i++) {
hashArr2[i] = seq2[i].hashCode();
}
return pairwiseBitwiseSubset(hashArr1, hashArr2);
}
#endif
#endif /* (defined(INT) || defined(LONG)) */
#if 0
#ifdef NUMERIC
// These methods aren't used to express any invariants; no need for them.
// /**
// * Requires: seq.length > 0
// * Returns the minimum element in the array.
// */
// /* pure */ public static _TYPE min(_TYPE[] seq) {
// // assert seq.length > 0;
// _TYPE retval = seq[0];
// for (int i = 1 ; i < seq.length ; i++) {
// if (lt(seq[i], retval)) {
// retval = seq[i];
// }
// }
// return retval;
// }
// /**
// * Requires: seq.length > 0
// * Returns the minimum element in the array.
// */
// /* pure */ public static _TYPE max(_TYPE[] seq) {
// // assert seq.length > 0;
// _TYPE retval = seq[0];
// for (int i = 1 ; i < seq.length ; i++) {
// if (gt(seq[i], retval)) {
// retval = seq[i];
// }
// }
// return retval;
// }
#endif
#endif /* 0 */
/**
* Returns the array { seq1[0], ..., seq1[seq1.length-1], seq2[0], ... , seq2[seq2.length-1] } .
*
* <p>If either array is null, returns null. If either array is empty, returns only those
* elements in the other array. If both arrays are empty, returns a new empty array.
*/
@SideEffectFree
public static _TYPE @PolyNull [] concat(_TYPE @PolyNull [] seq1, _TYPE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
return ArraysPlume.concat(seq1, seq2);
}
#ifdef COMPATIBLE
@SideEffectFree
public static CAST_TYPE @PolyNull [] concat(_TYPE @PolyNull [] seq1, COMPATIBLE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
// Cannot just use ArraysPlume.concat because the two arrays
// have different types. This essentially inlines that method.
int newLength = seq1.length + seq2.length;
CAST_TYPE[] retval = new CAST_TYPE[newLength];
#ifdef CAST_TYPE_IS_DIFFERENT_THAN_COMPATIBLE
System.arraycopy(seq1, 0, retval, 0, seq1.length);
for (int j = 0 ; j < seq2.length ; j++) {
retval[seq1.length + j] = seq2[j];
}
#else
for (int j = 0 ; j < seq1.length ; j++) {
retval[j] = seq1[j];
}
System.arraycopy(seq2, 0, retval, seq1.length, seq2.length);
#endif
return retval;
}
#endif
/**
* Returns an array that is equivalent to the set union of seq1 and seq2. This method gives no
* assurances about the order or repetition of elements: elements may be repeated, and their
* order may be different from the order of elements in seq1 and seq2.
*/
@SideEffectFree
public static _TYPE @PolyNull [] union(_TYPE @PolyNull [] seq1, _TYPE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
return concat(seq1, seq2);
}
#ifdef COMPATIBLE
@Pure
public static CAST_TYPE @PolyNull [] union(_TYPE @PolyNull [] seq1, COMPATIBLE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
return concat(seq1, seq2);
}
#endif
/**
* Returns an array that is equivalent to the set intersection of seq1 and seq2. This method
* gives no assurances about the order or repetition of elements: elements may be repeated, and
* their order may be different from the order of elements in seq1 and seq2.
*/
@Pure
public static _TYPE @PolyNull [] intersection(_TYPE @PolyNull [] seq1, _TYPE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
_TYPE[] intermediate = new _TYPE[Math.min(seq1.length, seq2.length)];
int length = 0;
for (int i = 0 ; i < seq1.length ; i++) {
if (memberOf(seq1[i], seq2) ) {
intermediate[length++] = seq1[i];
}
}
return ArraysPlume.subarray(intermediate, 0, length);
}
#ifdef COMPATIBLE
@Pure
public static CAST_TYPE @PolyNull [] intersection(_TYPE @PolyNull [] seq1, COMPATIBLE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
CAST_TYPE[] intermediate = new CAST_TYPE[Math.min(seq1.length, seq2.length)];
int length = 0;
for (int i = 0 ; i < seq1.length ; i++) {
if (memberOf(seq1[i], seq2) ) {
intermediate[length++] = seq1[i];
}
}
return ArraysPlume.subarray(intermediate, 0, length);
}
#endif
/**
* Returns an array that is equivalent to the set difference of seq1 and seq2. This method gives
* no assurances about the order or repetition of elements: elements may be repeated, and their
* order may be different from the order of elements in seq1 and seq2.
*/
@Pure
public static _TYPE @PolyNull [] setDiff(_TYPE @PolyNull [] seq1, _TYPE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
_TYPE[] intermediate = new _TYPE[seq1.length];
int length = 0;
for (int i = 0 ; i < seq1.length ; i++) {
if (!memberOf(seq1[i], seq2)) {
intermediate[length++] = seq1[i];
}
}
return ArraysPlume.subarray(intermediate, 0, length);
}
#ifdef COMPATIBLE
@Pure
public static CAST_TYPE @PolyNull [] setDiff(_TYPE @PolyNull [] seq1, COMPATIBLE @PolyNull [] seq2) {
if (seq1 == null) {
return null;
}
if (seq2 == null) {
return null;
}
CAST_TYPE[] intermediate = new CAST_TYPE[seq1.length];
int length = 0;
for (int i = 0 ; i < seq1.length ; i++) {
if (!memberOf(seq1[i], seq2)) {
intermediate[length++] = seq1[i];
}
}
return ArraysPlume.subarray(intermediate, 0, length);
}
#endif
/** Returns true iff seq1 and seq2 are equal when considered as sets. */
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean setEqual(_TYPE @Nullable [] seq1, _TYPE @Nullable [] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
for (int i = 0; i < seq1.length ; i++) {
if (!memberOf(seq1[i], seq2) ) {
return false;
}
}
for (int i = 0; i < seq2.length ; i++) {
if (!memberOf(seq2[i], seq1) ) {
return false;
}
}
return true;
}
#ifdef COMPATIBLE
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean setEqual(_TYPE @Nullable [] seq1, COMPATIBLE @Nullable [] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
for (int i = 0; i < seq1.length ; i++) {
if (!memberOf(seq1[i], seq2) ) {
return false;
}
}
for (int i = 0; i < seq2.length ; i++) {
if (!memberOf(seq2[i], seq1) ) {
return false;
}
}
return true;
}
#endif
/** True iff seq1 is the reverse of seq2.
*
* Meaning (in pseudo-FOL):
*
* <pre>
* /\ seq1.length == seq2.length
* /\ forall i in { 0..seq1.length-1 } : seq1[i] == seq2[seq2.length-1-i]
* </pre>
*
*/
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean isReverse(_TYPE[] seq1, _TYPE[] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
int length = seq1.length;
for (int i = 0 ; i < length ; i++) {
if (ne(seq1[i], seq2[length - i - 1])) {
return false;
}
}
return true;
}
#if (defined(OBJECT))
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean isReverse(@PolyNull Collection<? extends _TYPE> seq1, _TYPE @Nullable [] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
_TYPE[] seq1_array = seq1.toArray(new _TYPE[]{});
return isReverse(seq1_array, seq2);
}
#endif
#ifdef COMPATIBLE
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean isReverse(_TYPE @Nullable [] seq1, COMPATIBLE @Nullable [] seq2) {
if (!sameLength(seq1, seq2)) {
return false;
}
assert seq1 != null && seq2 != null; // because sameLength() = true
int length = seq1.length;
for (int i = 0 ; i < length ; i++) {
if (ne(seq1[i], seq2[length - i - 1])) {
return false;
}
}
return true;
}
#endif
#if 0
This has nothing to do with INT.
The "defined(INT)" test ensures that it only appears once in the output.
#endif
#if (defined(INT))
/** True iff all elements in elts occur once or more in arr;
* that is, elts is a subset of arr.
*
* Meaning (in pseudo-FOL):
*
* forall i in { 0..elt.length-1 } : elt[i] element_of arr
*
*/
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean subsetOf(@Nullable Object elts, @Nullable Object arr) {
if (elts == null) {
return false;
}
if (arr == null) {
return false;
}
if (!(elts.getClass().isArray() && arr.getClass().isArray())) {
// throw new IllegalArgumentException("both arguments must be arrays.");
return false;
}
// We know that the two arguments are arrays of different types; if
// they had been of the same type, then one of the more specific
// overriding versions of this method would have been called.
// This implementation simply calls either subsetOf(long[], long[]) or
// subsetOf(double[], double[]).
Class<?> eltsType = elts.getClass().getComponentType();
Class<?> arrType = arr.getClass().getComponentType();
if (isIntegralType(eltsType) && isIntegralType(arrType)) {
// Both arrays are int/long.
// Cast both arrays to long and call subsetOf(long[],long[]).
long[] elts_long;
if (eltsType == Long.class) {
elts_long = (long[]) elts;
} else {
elts_long = new long[Array.getLength(elts)];
for (int i = 0 ; i < elts_long.length ; i++) {
elts_long[i] = Array.getLong(elts, i);
}
}
long[] arr_long;
if (arrType == Long.class) {
arr_long = (long[]) arr;
} else {
arr_long = new long[Array.getLength(arr)];
for (int i = 0 ; i < arr_long.length ; i++) {
arr_long[i] = Array.getLong(arr, i);
}
}
return subsetOf(elts_long, arr_long);
} else if (isNumericType(eltsType) && isNumericType(arrType)) {
// At least one array is float/double.
// Cast both arrays to double and call subsetOf(double[],double[])
double[] elts_double = new double[Array.getLength(elts)];
for (int i = 0 ; i < elts_double.length ; i++) {
elts_double[i] = Array.getDouble(elts, i);
}
double[] arr_double = new double[Array.getLength(arr)];
for (int i = 0 ; i < arr_double.length ; i++) {
arr_double[i] = Array.getDouble(arr, i);
}
return subsetOf(elts_double, arr_double);
} else {
// throw new IllegalArgumentException("both arguments must be arrays of numeric types.");
return false;
}
}
#endif
/** True iff seq1 is a subset of seq2, when the sequences are considered as sets. */
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean subsetOf(_TYPE @Nullable [] seq1, _TYPE @Nullable [] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
for (int i = 0 ; i < seq1.length ; i++) {
if (!memberOf(seq1[i], seq2)) {
return false;
}
}
return true;
}
#ifdef COMPATIBLE
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean subsetOf(_TYPE @Nullable [] seq1, COMPATIBLE @Nullable [] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
for (int i = 0 ; i < seq1.length ; i++) {
if (!memberOf(seq1[i], seq2)) {
return false;
}
}
return true;
}
#endif
#if (defined(OBJECT))
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean subsetOf(@Nullable Collection<? extends _TYPE> seq1, _TYPE @Nullable [] seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
_TYPE[] seq1_array = seq1.toArray(new _TYPE[]{});
return subsetOf(seq1_array, seq2);
}
@EnsuresNonNullIf(result=true, expression={"#1","#2"})
@Pure
public static boolean subsetOf(_TYPE @Nullable [] seq1, @Nullable Collection<? extends _TYPE> seq2) {
if (seq1 == null) {
return false;
}
if (seq2 == null) {
return false;
}
_TYPE[] seq2_array = seq2.toArray(new _TYPE[]{});
return subsetOf(seq1, seq2_array);
}
#endif
/** Returns true iff seq contains no duplicate elements. */
@EnsuresNonNullIf(result=true, expression="#1")
@Pure
public static boolean noDups(_TYPE @Nullable [] seq) {
if (seq == null) {
return false;
}
return ArraysPlume.noDuplicates(seq);
}
/** Returns true iff elt is in array arr. */
@EnsuresNonNullIf(result=true, expression="#2")
@Pure
public static boolean memberOf(_TYPE elt, _TYPE @Nullable [] arr) {
if (arr == null) {
return false;
}
for (int i = 0 ; i < arr.length ; i++) {
if (eq(arr[i], elt)) {