@grain/stdlib 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/array.gr +61 -1
- package/array.md +113 -0
- package/bigint.md +30 -30
- package/buffer.gr +24 -22
- package/char.gr +2 -2
- package/float32.md +3 -3
- package/float64.md +3 -3
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +360 -0
- package/immutablepriorityqueue.md +291 -0
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/list.gr +75 -2
- package/list.md +110 -0
- package/map.gr +1 -2
- package/marshal.gr +1058 -0
- package/marshal.md +76 -0
- package/number.gr +689 -23
- package/number.md +362 -27
- package/package.json +1 -1
- package/pervasives.gr +16 -5
- package/pervasives.md +28 -0
- package/priorityqueue.gr +261 -0
- package/priorityqueue.md +309 -0
- package/queue.gr +14 -1
- package/queue.md +16 -1
- package/regex.gr +90 -67
- package/runtime/bigint.gr +4 -4
- package/runtime/compare.gr +179 -0
- package/runtime/compare.md +6 -0
- package/runtime/equal.gr +3 -3
- package/runtime/exception.gr +9 -5
- package/runtime/exception.md +8 -2
- package/runtime/gc.gr +2 -1
- package/runtime/malloc.gr +1 -3
- package/runtime/numberUtils.gr +11 -11
- package/runtime/numbers.gr +423 -100
- package/runtime/numbers.md +50 -0
- package/runtime/string.gr +4 -2
- package/set.gr +26 -27
- package/stack.gr +12 -0
- package/stack.md +15 -0
- package/string.gr +409 -53
- package/string.md +164 -1
- package/sys/file.gr +4 -4
- package/sys/file.md +3 -3
- package/sys/process.gr +3 -3
- package/sys/process.md +3 -3
- package/sys/random.gr +2 -2
- package/sys/random.md +2 -2
- package/sys/time.gr +2 -2
- package/sys/time.md +2 -2
package/runtime/numbers.gr
CHANGED
|
@@ -20,6 +20,7 @@ primitive (||): (Bool, Bool) -> Bool = "@or"
|
|
|
20
20
|
primitive throw: Exception -> a = "@throw"
|
|
21
21
|
|
|
22
22
|
exception UnknownNumberTag
|
|
23
|
+
exception InvariantViolation
|
|
23
24
|
|
|
24
25
|
import {
|
|
25
26
|
newRational,
|
|
@@ -78,7 +79,29 @@ export let isFloat = x => {
|
|
|
78
79
|
if (isBoxedNumber(x)) {
|
|
79
80
|
let tag = WasmI32.load(x, 4n)
|
|
80
81
|
WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) ||
|
|
81
|
-
|
|
82
|
+
WasmI32.eq(tag, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
83
|
+
} else {
|
|
84
|
+
false
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@unsafe
|
|
89
|
+
export let isInteger = x => {
|
|
90
|
+
if (isBoxedNumber(x)) {
|
|
91
|
+
let tag = WasmI32.load(x, 4n)
|
|
92
|
+
WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG) ||
|
|
93
|
+
WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG) ||
|
|
94
|
+
WasmI32.eq(tag, Tags._GRAIN_BIGINT_BOXED_NUM_TAG)
|
|
95
|
+
} else {
|
|
96
|
+
true
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@unsafe
|
|
101
|
+
export let isRational = x => {
|
|
102
|
+
if (isBoxedNumber(x)) {
|
|
103
|
+
let tag = WasmI32.load(x, 4n)
|
|
104
|
+
WasmI32.eq(tag, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG)
|
|
82
105
|
} else {
|
|
83
106
|
false
|
|
84
107
|
}
|
|
@@ -495,13 +518,13 @@ let isIntegerF64 = value => {
|
|
|
495
518
|
@unsafe
|
|
496
519
|
let isSafeIntegerF32 = value => {
|
|
497
520
|
WasmF32.le(WasmF32.abs(value), _F32_MAX_SAFE_INTEGER) &&
|
|
498
|
-
|
|
521
|
+
WasmF32.eq(WasmF32.trunc(value), value)
|
|
499
522
|
}
|
|
500
523
|
|
|
501
524
|
@unsafe
|
|
502
525
|
let isSafeIntegerF64 = value => {
|
|
503
526
|
WasmF64.le(WasmF64.abs(value), _F64_MAX_SAFE_INTEGER) &&
|
|
504
|
-
|
|
527
|
+
WasmF64.eq(WasmF64.trunc(value), value)
|
|
505
528
|
}
|
|
506
529
|
|
|
507
530
|
/** Number-aware equality checking
|
|
@@ -541,12 +564,12 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
541
564
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
542
565
|
let yBoxedVal = boxedFloat32Number(y)
|
|
543
566
|
isSafeIntegerF32(yBoxedVal) &&
|
|
544
|
-
|
|
567
|
+
WasmF32.eq(WasmF32.convertI32S(xval), yBoxedVal)
|
|
545
568
|
},
|
|
546
569
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
547
570
|
let yBoxedVal = boxedFloat64Number(y)
|
|
548
571
|
isSafeIntegerF64(yBoxedVal) &&
|
|
549
|
-
|
|
572
|
+
WasmF64.eq(WasmF64.convertI32S(xval), yBoxedVal)
|
|
550
573
|
},
|
|
551
574
|
_ => {
|
|
552
575
|
throw UnknownNumberTag
|
|
@@ -583,12 +606,12 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
583
606
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
584
607
|
let yBoxedVal = boxedFloat32Number(y)
|
|
585
608
|
isSafeIntegerF32(yBoxedVal) &&
|
|
586
|
-
|
|
609
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF32S(yBoxedVal))
|
|
587
610
|
},
|
|
588
611
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
589
612
|
let yBoxedVal = boxedFloat64Number(y)
|
|
590
613
|
isSafeIntegerF64(yBoxedVal) &&
|
|
591
|
-
|
|
614
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF64S(yBoxedVal))
|
|
592
615
|
},
|
|
593
616
|
_ => {
|
|
594
617
|
throw UnknownNumberTag
|
|
@@ -635,7 +658,7 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
635
658
|
BI.toFloat32(xNumerator),
|
|
636
659
|
BI.toFloat32(xDenominator)
|
|
637
660
|
)
|
|
638
|
-
// TODO
|
|
661
|
+
// TODO(#303): maybe we should have some sort of tolerance?
|
|
639
662
|
WasmF32.eq(xAsFloat, yBoxedVal)
|
|
640
663
|
},
|
|
641
664
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
@@ -644,7 +667,7 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
644
667
|
BI.toFloat64(xNumerator),
|
|
645
668
|
BI.toFloat64(xDenominator)
|
|
646
669
|
)
|
|
647
|
-
// TODO
|
|
670
|
+
// TODO(#303): maybe we should have some sort of tolerance?
|
|
648
671
|
WasmF64.eq(xAsFloat, yBoxedVal)
|
|
649
672
|
},
|
|
650
673
|
_ => {
|
|
@@ -686,12 +709,12 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
686
709
|
},
|
|
687
710
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
688
711
|
let yBoxedVal = boxedFloat32Number(y)
|
|
689
|
-
// TODO
|
|
712
|
+
// TODO(#303): maybe we should have some sort of tolerance?
|
|
690
713
|
WasmF64.eq(x, WasmF64.promoteF32(yBoxedVal))
|
|
691
714
|
},
|
|
692
715
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
693
716
|
let yBoxedVal = boxedFloat64Number(y)
|
|
694
|
-
// TODO
|
|
717
|
+
// TODO(#303): maybe we should have some sort of tolerance?
|
|
695
718
|
WasmF64.eq(x, yBoxedVal)
|
|
696
719
|
},
|
|
697
720
|
_ => {
|
|
@@ -820,14 +843,16 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
820
843
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
821
844
|
let xval = WasmI64.extendI32S(xval)
|
|
822
845
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
823
|
-
let result =
|
|
846
|
+
let result =
|
|
847
|
+
if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
824
848
|
else WasmI64.add(xval, yBoxedVal)
|
|
825
849
|
reducedInteger(result)
|
|
826
850
|
},
|
|
827
851
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
828
852
|
let yBoxedVal = boxedInt64Number(y)
|
|
829
853
|
let xval64 = WasmI64.extendI32S(xval)
|
|
830
|
-
let result =
|
|
854
|
+
let result =
|
|
855
|
+
if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
831
856
|
else WasmI64.add(xval64, yBoxedVal)
|
|
832
857
|
if (
|
|
833
858
|
WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64) ||
|
|
@@ -861,7 +886,8 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
861
886
|
let yDenominator = boxedRationalDenominator(y)
|
|
862
887
|
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
863
888
|
Memory.decRef(xBig)
|
|
864
|
-
let result =
|
|
889
|
+
let result =
|
|
890
|
+
if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
865
891
|
else BI.add(expandedXNumerator, yNumerator)
|
|
866
892
|
let ret = reducedFractionBigInt(result, yDenominator)
|
|
867
893
|
Memory.decRef(expandedXNumerator)
|
|
@@ -871,15 +897,16 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
871
897
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
872
898
|
let yBoxedVal = boxedFloat32Number(y)
|
|
873
899
|
let xval = WasmF32.convertI32S(xval)
|
|
874
|
-
let result =
|
|
900
|
+
let result =
|
|
901
|
+
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
875
902
|
else WasmF32.add(xval, yBoxedVal)
|
|
876
|
-
// TODO: (#304) is this safe?
|
|
877
903
|
newFloat32(result)
|
|
878
904
|
},
|
|
879
905
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
880
906
|
let yBoxedVal = boxedFloat64Number(y)
|
|
881
907
|
let xval = WasmF64.convertI32S(xval)
|
|
882
|
-
let result =
|
|
908
|
+
let result =
|
|
909
|
+
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
883
910
|
else WasmF64.add(xval, yBoxedVal)
|
|
884
911
|
newFloat64(result)
|
|
885
912
|
},
|
|
@@ -918,14 +945,16 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
918
945
|
match (yBoxedNumberTag) {
|
|
919
946
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
920
947
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
921
|
-
let result =
|
|
948
|
+
let result =
|
|
949
|
+
if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
922
950
|
else WasmI64.add(xval, yBoxedVal)
|
|
923
951
|
reducedInteger(result)
|
|
924
952
|
},
|
|
925
953
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
926
954
|
let yBoxedVal = boxedInt64Number(y)
|
|
927
955
|
let xval64 = xval
|
|
928
|
-
let result =
|
|
956
|
+
let result =
|
|
957
|
+
if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
929
958
|
else WasmI64.add(xval64, yBoxedVal)
|
|
930
959
|
if (
|
|
931
960
|
WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64) ||
|
|
@@ -959,7 +988,8 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
959
988
|
let yDenominator = boxedRationalDenominator(y)
|
|
960
989
|
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
961
990
|
Memory.decRef(xBig)
|
|
962
|
-
let result =
|
|
991
|
+
let result =
|
|
992
|
+
if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
963
993
|
else BI.add(expandedXNumerator, yNumerator)
|
|
964
994
|
let ret = reducedFractionBigInt(result, yDenominator)
|
|
965
995
|
Memory.decRef(expandedXNumerator)
|
|
@@ -969,15 +999,16 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
969
999
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
970
1000
|
let xval = WasmF32.convertI64S(xval)
|
|
971
1001
|
let yBoxedVal = boxedFloat32Number(y)
|
|
972
|
-
let result =
|
|
1002
|
+
let result =
|
|
1003
|
+
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
973
1004
|
else WasmF32.add(xval, yBoxedVal)
|
|
974
|
-
// TODO(#304): this isn't safe enough
|
|
975
1005
|
newFloat32(result)
|
|
976
1006
|
},
|
|
977
1007
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
978
1008
|
let xval = WasmF64.convertI64S(xval)
|
|
979
1009
|
let yBoxedVal = boxedFloat64Number(y)
|
|
980
|
-
let result =
|
|
1010
|
+
let result =
|
|
1011
|
+
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
981
1012
|
else WasmF64.add(xval, yBoxedVal)
|
|
982
1013
|
newFloat64(result)
|
|
983
1014
|
},
|
|
@@ -1071,7 +1102,8 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1071
1102
|
let yNumerator = boxedRationalNumerator(y)
|
|
1072
1103
|
let yDenominator = boxedRationalDenominator(y)
|
|
1073
1104
|
let expandedXNumerator = BI.mul(x, yDenominator)
|
|
1074
|
-
let result =
|
|
1105
|
+
let result =
|
|
1106
|
+
if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
1075
1107
|
else BI.add(expandedXNumerator, yNumerator)
|
|
1076
1108
|
Memory.decRef(expandedXNumerator)
|
|
1077
1109
|
let ret = reducedFractionBigInt(result, yDenominator)
|
|
@@ -1081,15 +1113,16 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1081
1113
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1082
1114
|
let xval = BI.toFloat32(x)
|
|
1083
1115
|
let yBoxedVal = boxedFloat32Number(y)
|
|
1084
|
-
let result =
|
|
1116
|
+
let result =
|
|
1117
|
+
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
1085
1118
|
else WasmF32.add(xval, yBoxedVal)
|
|
1086
|
-
// TODO: (#304) this isn't safe enough
|
|
1087
1119
|
newFloat32(result)
|
|
1088
1120
|
},
|
|
1089
1121
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1090
1122
|
let xval = BI.toFloat64(x)
|
|
1091
1123
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1092
|
-
let result =
|
|
1124
|
+
let result =
|
|
1125
|
+
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
1093
1126
|
else WasmF64.add(xval, yBoxedVal)
|
|
1094
1127
|
newFloat64(result)
|
|
1095
1128
|
},
|
|
@@ -1108,7 +1141,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1108
1141
|
let yval = untagSimple(y)
|
|
1109
1142
|
let yBig = BI.makeWrappedInt32(yval)
|
|
1110
1143
|
let expandedYNumerator = BI.mul(xDenominator, yBig)
|
|
1111
|
-
let result =
|
|
1144
|
+
let result =
|
|
1145
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1112
1146
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1113
1147
|
Memory.decRef(expandedYNumerator)
|
|
1114
1148
|
Memory.decRef(yBig)
|
|
@@ -1125,7 +1159,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1125
1159
|
let yNumerator = boxedRationalNumerator(y)
|
|
1126
1160
|
let yDenominator = boxedRationalDenominator(y)
|
|
1127
1161
|
if (BI.eq(xDenominator, yDenominator)) {
|
|
1128
|
-
let newNumerator =
|
|
1162
|
+
let newNumerator =
|
|
1163
|
+
if (isSub) BI.sub(xNumerator, yNumerator)
|
|
1129
1164
|
else BI.add(xNumerator, yNumerator)
|
|
1130
1165
|
let ret = reducedFractionBigInt(newNumerator, xDenominator)
|
|
1131
1166
|
Memory.decRef(newNumerator)
|
|
@@ -1133,7 +1168,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1133
1168
|
} else {
|
|
1134
1169
|
let numerator1 = BI.mul(xNumerator, yDenominator)
|
|
1135
1170
|
let numerator2 = BI.mul(yNumerator, xDenominator)
|
|
1136
|
-
let numerator =
|
|
1171
|
+
let numerator =
|
|
1172
|
+
if (isSub) BI.sub(numerator1, numerator2)
|
|
1137
1173
|
else BI.add(numerator1, numerator2)
|
|
1138
1174
|
let denominator = BI.mul(xDenominator, yDenominator)
|
|
1139
1175
|
let ret = reducedFractionBigInt(numerator, denominator)
|
|
@@ -1147,7 +1183,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1147
1183
|
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1148
1184
|
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1149
1185
|
Memory.decRef(yBig)
|
|
1150
|
-
let result =
|
|
1186
|
+
let result =
|
|
1187
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1151
1188
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1152
1189
|
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1153
1190
|
Memory.decRef(expandedYNumerator)
|
|
@@ -1158,7 +1195,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1158
1195
|
let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
|
|
1159
1196
|
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1160
1197
|
Memory.decRef(yBig)
|
|
1161
|
-
let result =
|
|
1198
|
+
let result =
|
|
1199
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1162
1200
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1163
1201
|
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1164
1202
|
Memory.decRef(expandedYNumerator)
|
|
@@ -1167,7 +1205,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1167
1205
|
},
|
|
1168
1206
|
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1169
1207
|
let expandedYNumerator = BI.mul(xDenominator, y)
|
|
1170
|
-
let result =
|
|
1208
|
+
let result =
|
|
1209
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1171
1210
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1172
1211
|
Memory.decRef(expandedYNumerator)
|
|
1173
1212
|
let ret = reducedFractionBigInt(result, xDenominator)
|
|
@@ -1179,7 +1218,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1179
1218
|
BI.toFloat32(xNumerator),
|
|
1180
1219
|
BI.toFloat32(xDenominator)
|
|
1181
1220
|
)
|
|
1182
|
-
let result =
|
|
1221
|
+
let result =
|
|
1222
|
+
if (isSub) WasmF32.sub(xval, boxedFloat32Number(y))
|
|
1183
1223
|
else WasmF32.add(xval, boxedFloat32Number(y))
|
|
1184
1224
|
newFloat32(result)
|
|
1185
1225
|
},
|
|
@@ -1188,8 +1228,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1188
1228
|
let xdenfloat = BI.toFloat64(xDenominator)
|
|
1189
1229
|
let xval = WasmF64.div(xnumfloat, xdenfloat)
|
|
1190
1230
|
let yval = boxedFloat64Number(y)
|
|
1191
|
-
let result =
|
|
1192
|
-
else WasmF64.add(xval, yval)
|
|
1231
|
+
let result =
|
|
1232
|
+
if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
1193
1233
|
let ret = newFloat64(result)
|
|
1194
1234
|
ret
|
|
1195
1235
|
},
|
|
@@ -1326,7 +1366,6 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
1326
1366
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1327
1367
|
let xval = WasmF32.convertI64S(xval)
|
|
1328
1368
|
let yBoxedVal = boxedFloat32Number(y)
|
|
1329
|
-
// TODO: (#304) is this safe?
|
|
1330
1369
|
if (isDivide) {
|
|
1331
1370
|
newFloat32(WasmF32.div(xval, yBoxedVal))
|
|
1332
1371
|
} else {
|
|
@@ -1385,6 +1424,13 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
|
|
|
1385
1424
|
Memory.decRef(yBig)
|
|
1386
1425
|
ret
|
|
1387
1426
|
},
|
|
1427
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1428
|
+
if (isDivide) {
|
|
1429
|
+
reducedBigInteger(BI.div(x, y))
|
|
1430
|
+
} else {
|
|
1431
|
+
reducedBigInteger(BI.mul(x, y))
|
|
1432
|
+
}
|
|
1433
|
+
},
|
|
1388
1434
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1389
1435
|
let yNumerator = boxedRationalNumerator(y)
|
|
1390
1436
|
let yDenominator = boxedRationalDenominator(y)
|
|
@@ -1407,7 +1453,6 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
|
|
|
1407
1453
|
// we can only fit rather small bigints (<4 limbs) into an F32
|
|
1408
1454
|
let xval = BI.toFloat64(x)
|
|
1409
1455
|
let yBoxedVal = WasmF64.promoteF32(boxedFloat32Number(y))
|
|
1410
|
-
// TODO: (#304) is this safe?
|
|
1411
1456
|
if (isDivide) {
|
|
1412
1457
|
newFloat64(WasmF64.div(xval, yBoxedVal))
|
|
1413
1458
|
} else {
|
|
@@ -1530,10 +1575,11 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1530
1575
|
let yDenominator = boxedRationalDenominator(y)
|
|
1531
1576
|
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
1532
1577
|
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
1533
|
-
|
|
1534
|
-
|
|
1578
|
+
let numerator =
|
|
1579
|
+
if (isDivide) BI.mul(xNumerator, yDenominator)
|
|
1535
1580
|
else BI.mul(xNumerator, yNumerator)
|
|
1536
|
-
let denominator =
|
|
1581
|
+
let denominator =
|
|
1582
|
+
if (isDivide) BI.mul(xDenominator, yNumerator)
|
|
1537
1583
|
else BI.mul(xDenominator, yDenominator)
|
|
1538
1584
|
reducedFractionBigInt(numerator, denominator)
|
|
1539
1585
|
},
|
|
@@ -1669,7 +1715,8 @@ let numberMod = (x, y) => {
|
|
|
1669
1715
|
WasmI64.gtS(xval, 0N) && WasmI64.ltS(yval, 0N)
|
|
1670
1716
|
) {
|
|
1671
1717
|
let modval = WasmI64.remS(i64abs(xval), i64abs(yval))
|
|
1672
|
-
let result =
|
|
1718
|
+
let result =
|
|
1719
|
+
if (WasmI64.ne(modval, 0N))
|
|
1673
1720
|
WasmI64.mul(
|
|
1674
1721
|
WasmI64.sub(i64abs(yval), modval),
|
|
1675
1722
|
if (WasmI64.ltS(yval, 0N)) -1N else 1N
|
|
@@ -1681,9 +1728,18 @@ let numberMod = (x, y) => {
|
|
|
1681
1728
|
}
|
|
1682
1729
|
|
|
1683
1730
|
/*
|
|
1684
|
-
* =====
|
|
1685
|
-
*
|
|
1686
|
-
*
|
|
1731
|
+
* ===== COMPARISONS =====
|
|
1732
|
+
* Int/int and float/float comparisons are always accurate.
|
|
1733
|
+
* Rational/rational comparisons are approximations with the exception of
|
|
1734
|
+
* equality, which is always accurate.
|
|
1735
|
+
*
|
|
1736
|
+
* Values compared to floats or rationals are first converted to floats.
|
|
1737
|
+
*
|
|
1738
|
+
* All comparison operators consider NaN not equal to, less than, or greater
|
|
1739
|
+
* than NaN, with the exception of `compare`, which considers NaN equal to
|
|
1740
|
+
* itself and otherwise smaller than any other float value. This provides a
|
|
1741
|
+
* total order (https://en.wikipedia.org/wiki/Total_order) over all numerical
|
|
1742
|
+
* values, making `compare` suitable for sorting or ordering.
|
|
1687
1743
|
*/
|
|
1688
1744
|
|
|
1689
1745
|
@unsafe
|
|
@@ -1721,81 +1777,286 @@ let cmpBigInt = (x: WasmI32, y: WasmI32) => {
|
|
|
1721
1777
|
}
|
|
1722
1778
|
}
|
|
1723
1779
|
|
|
1724
|
-
// TODO: (#305) is this safe? I think it's safe?
|
|
1725
1780
|
@unsafe
|
|
1726
|
-
|
|
1727
|
-
let
|
|
1728
|
-
|
|
1729
|
-
if (isBigInt(xw32)) {
|
|
1730
|
-
WasmI32.ltS(cmpBigInt(xw32, yw32), 0n)
|
|
1731
|
-
} else if (isBigInt(yw32)) {
|
|
1732
|
-
WasmI32.geS(cmpBigInt(yw32, xw32), 0n)
|
|
1781
|
+
let cmpFloat = (x: WasmI32, y: WasmI32, is64: Bool, totalOrdering: Bool) => {
|
|
1782
|
+
let xf = if (is64) {
|
|
1783
|
+
boxedFloat64Number(x)
|
|
1733
1784
|
} else {
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1785
|
+
WasmF64.promoteF32(boxedFloat32Number(x))
|
|
1786
|
+
}
|
|
1787
|
+
if (isSimpleNumber(y)) {
|
|
1788
|
+
let yf = WasmF64.convertI32S(untagSimple(y))
|
|
1789
|
+
// special NaN cases
|
|
1790
|
+
if (totalOrdering && WasmF64.ne(xf, xf)) {
|
|
1791
|
+
if (WasmF64.ne(yf, yf)) {
|
|
1792
|
+
0n
|
|
1793
|
+
} else {
|
|
1794
|
+
-1n
|
|
1795
|
+
}
|
|
1796
|
+
} else if (totalOrdering && WasmF64.ne(yf, yf)) {
|
|
1797
|
+
if (WasmF64.ne(xf, xf)) {
|
|
1798
|
+
0n
|
|
1799
|
+
} else {
|
|
1800
|
+
1n
|
|
1801
|
+
}
|
|
1802
|
+
} else {
|
|
1803
|
+
if (WasmF64.lt(xf, yf)) -1n else if (WasmF64.gt(xf, yf)) 1n else 0n
|
|
1804
|
+
}
|
|
1805
|
+
} else {
|
|
1806
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1807
|
+
if (yBoxedNumberTag == Tags._GRAIN_BIGINT_BOXED_NUM_TAG) {
|
|
1808
|
+
WasmI32.sub(0n, cmpBigInt(y, x))
|
|
1809
|
+
} else {
|
|
1810
|
+
let yf = match (yBoxedNumberTag) {
|
|
1811
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1812
|
+
WasmF64.convertI32S(boxedInt32Number(y))
|
|
1813
|
+
},
|
|
1814
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1815
|
+
WasmF64.convertI64S(boxedInt64Number(y))
|
|
1816
|
+
},
|
|
1817
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1818
|
+
throw InvariantViolation
|
|
1819
|
+
},
|
|
1820
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1821
|
+
WasmF64.div(
|
|
1822
|
+
BI.toFloat64(boxedRationalNumerator(y)),
|
|
1823
|
+
BI.toFloat64(boxedRationalDenominator(y))
|
|
1824
|
+
)
|
|
1825
|
+
},
|
|
1826
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1827
|
+
WasmF64.promoteF32(boxedFloat32Number(y))
|
|
1828
|
+
},
|
|
1829
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1830
|
+
boxedFloat64Number(y)
|
|
1831
|
+
},
|
|
1832
|
+
_ => {
|
|
1833
|
+
throw UnknownNumberTag
|
|
1834
|
+
},
|
|
1835
|
+
}
|
|
1836
|
+
// special NaN cases
|
|
1837
|
+
if (totalOrdering && WasmF64.ne(xf, xf)) {
|
|
1838
|
+
if (WasmF64.ne(yf, yf)) {
|
|
1839
|
+
0n
|
|
1840
|
+
} else {
|
|
1841
|
+
-1n
|
|
1842
|
+
}
|
|
1843
|
+
} else if (totalOrdering && WasmF64.ne(yf, yf)) {
|
|
1844
|
+
if (WasmF64.ne(xf, xf)) {
|
|
1845
|
+
0n
|
|
1846
|
+
} else {
|
|
1847
|
+
1n
|
|
1848
|
+
}
|
|
1849
|
+
} else {
|
|
1850
|
+
if (WasmF64.lt(xf, yf)) -1n else if (WasmF64.gt(xf, yf)) 1n else 0n
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1737
1853
|
}
|
|
1738
1854
|
}
|
|
1739
1855
|
|
|
1740
1856
|
@unsafe
|
|
1741
|
-
|
|
1742
|
-
let
|
|
1743
|
-
|
|
1744
|
-
if (isBigInt(xw32)) {
|
|
1745
|
-
WasmI32.gtS(cmpBigInt(xw32, yw32), 0n)
|
|
1746
|
-
} else if (isBigInt(yw32)) {
|
|
1747
|
-
WasmI32.leS(cmpBigInt(yw32, xw32), 0n)
|
|
1857
|
+
let cmpSmallInt = (x: WasmI32, y: WasmI32, is64: Bool, totalOrdering: Bool) => {
|
|
1858
|
+
let xi = if (is64) {
|
|
1859
|
+
boxedInt64Number(x)
|
|
1748
1860
|
} else {
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1861
|
+
WasmI64.extendI32S(boxedInt32Number(x))
|
|
1862
|
+
}
|
|
1863
|
+
if (isSimpleNumber(y)) {
|
|
1864
|
+
let yi = WasmI64.extendI32S(untagSimple(y))
|
|
1865
|
+
if (WasmI64.ltS(xi, yi)) -1n else if (WasmI64.gtS(xi, yi)) 1n else 0n
|
|
1866
|
+
} else {
|
|
1867
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1868
|
+
match (yBoxedNumberTag) {
|
|
1869
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1870
|
+
let yi = WasmI64.extendI32S(boxedInt32Number(y))
|
|
1871
|
+
if (WasmI64.ltS(xi, yi)) -1n else if (WasmI64.gtS(xi, yi)) 1n else 0n
|
|
1872
|
+
},
|
|
1873
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1874
|
+
let yi = boxedInt64Number(y)
|
|
1875
|
+
if (WasmI64.ltS(xi, yi)) -1n else if (WasmI64.gtS(xi, yi)) 1n else 0n
|
|
1876
|
+
},
|
|
1877
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1878
|
+
WasmI32.sub(0n, cmpBigInt(y, x))
|
|
1879
|
+
},
|
|
1880
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1881
|
+
// Rationals and ints are never considered equal
|
|
1882
|
+
if (
|
|
1883
|
+
WasmF64.lt(
|
|
1884
|
+
WasmF64.convertI64S(xi),
|
|
1885
|
+
WasmF64.div(
|
|
1886
|
+
BI.toFloat64(boxedRationalNumerator(y)),
|
|
1887
|
+
BI.toFloat64(boxedRationalDenominator(y))
|
|
1888
|
+
)
|
|
1889
|
+
)
|
|
1890
|
+
) -1n else 1n
|
|
1891
|
+
},
|
|
1892
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1893
|
+
WasmI32.sub(0n, cmpFloat(y, x, false, totalOrdering))
|
|
1894
|
+
},
|
|
1895
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1896
|
+
WasmI32.sub(0n, cmpFloat(y, x, true, totalOrdering))
|
|
1897
|
+
},
|
|
1898
|
+
_ => {
|
|
1899
|
+
throw UnknownNumberTag
|
|
1900
|
+
},
|
|
1901
|
+
}
|
|
1752
1902
|
}
|
|
1753
1903
|
}
|
|
1754
1904
|
|
|
1755
1905
|
@unsafe
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1906
|
+
let cmpRational = (x: WasmI32, y: WasmI32, totalOrdering: Bool) => {
|
|
1907
|
+
if (isSimpleNumber(y)) {
|
|
1908
|
+
let xf = WasmF64.div(
|
|
1909
|
+
BI.toFloat64(boxedRationalNumerator(x)),
|
|
1910
|
+
BI.toFloat64(boxedRationalDenominator(x))
|
|
1911
|
+
)
|
|
1912
|
+
// Rationals and ints are never considered equal
|
|
1913
|
+
if (WasmF64.lt(xf, WasmF64.convertI32S(untagSimple(y)))) -1n else 1n
|
|
1763
1914
|
} else {
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1915
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1916
|
+
match (yBoxedNumberTag) {
|
|
1917
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1918
|
+
WasmI32.sub(0n, cmpSmallInt(y, x, false, totalOrdering))
|
|
1919
|
+
},
|
|
1920
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1921
|
+
WasmI32.sub(0n, cmpSmallInt(y, x, true, totalOrdering))
|
|
1922
|
+
},
|
|
1923
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1924
|
+
WasmI32.sub(0n, cmpBigInt(y, x))
|
|
1925
|
+
},
|
|
1926
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1927
|
+
// Comparing rationals efficiently is an open problem
|
|
1928
|
+
// Producing a definitive answer is quite expensive, so if the two
|
|
1929
|
+
// values are not strictly equal we approximate an answer
|
|
1930
|
+
|
|
1931
|
+
let xNumerator = boxedRationalNumerator(x)
|
|
1932
|
+
let xDenominator = boxedRationalDenominator(x)
|
|
1933
|
+
let yNumerator = boxedRationalNumerator(y)
|
|
1934
|
+
let yDenominator = boxedRationalDenominator(y)
|
|
1935
|
+
|
|
1936
|
+
if (
|
|
1937
|
+
BI.cmp(xNumerator, yNumerator) == 0n &&
|
|
1938
|
+
BI.cmp(xDenominator, yDenominator) == 0n
|
|
1939
|
+
) {
|
|
1940
|
+
0n
|
|
1941
|
+
} else {
|
|
1942
|
+
let xf = WasmF64.div(
|
|
1943
|
+
BI.toFloat64(xNumerator),
|
|
1944
|
+
BI.toFloat64(xDenominator)
|
|
1945
|
+
)
|
|
1946
|
+
let yf = WasmF64.div(
|
|
1947
|
+
BI.toFloat64(yNumerator),
|
|
1948
|
+
BI.toFloat64(yDenominator)
|
|
1949
|
+
)
|
|
1950
|
+
if (WasmF64.lt(xf, yf)) -1n else 1n
|
|
1951
|
+
}
|
|
1952
|
+
},
|
|
1953
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1954
|
+
WasmI32.sub(0n, cmpFloat(y, x, false, totalOrdering))
|
|
1955
|
+
},
|
|
1956
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1957
|
+
WasmI32.sub(0n, cmpFloat(y, x, true, totalOrdering))
|
|
1958
|
+
},
|
|
1959
|
+
_ => {
|
|
1960
|
+
throw UnknownNumberTag
|
|
1961
|
+
},
|
|
1773
1962
|
}
|
|
1774
1963
|
}
|
|
1775
1964
|
}
|
|
1776
1965
|
|
|
1777
1966
|
@unsafe
|
|
1778
|
-
export let
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
WasmI32.leS(cmpBigInt(xw32, yw32), 0n)
|
|
1783
|
-
} else if (isBigInt(yw32)) {
|
|
1784
|
-
WasmI32.geS(cmpBigInt(yw32, xw32), 0n)
|
|
1785
|
-
} else {
|
|
1786
|
-
// Equality is finicky, so delegate
|
|
1787
|
-
let xval = coerceNumberToWasmF64(x)
|
|
1788
|
-
let yval = coerceNumberToWasmF64(y)
|
|
1789
|
-
if (WasmF64.gt(xval, yval)) {
|
|
1790
|
-
true
|
|
1967
|
+
export let cmp = (x: WasmI32, y: WasmI32, totalOrdering: Bool) => {
|
|
1968
|
+
if (isSimpleNumber(x)) {
|
|
1969
|
+
if (isSimpleNumber(y)) {
|
|
1970
|
+
if (WasmI32.ltS(x, y)) -1n else if (WasmI32.gtS(x, y)) 1n else 0n
|
|
1791
1971
|
} else {
|
|
1792
|
-
let
|
|
1793
|
-
|
|
1794
|
-
|
|
1972
|
+
let yBoxedNumberTag = boxedNumberTag(y)
|
|
1973
|
+
match (yBoxedNumberTag) {
|
|
1974
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
1975
|
+
WasmI32.sub(0n, cmpSmallInt(y, x, false, totalOrdering))
|
|
1976
|
+
},
|
|
1977
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
1978
|
+
WasmI32.sub(0n, cmpSmallInt(y, x, true, totalOrdering))
|
|
1979
|
+
},
|
|
1980
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1981
|
+
WasmI32.sub(0n, cmpBigInt(y, x))
|
|
1982
|
+
},
|
|
1983
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1984
|
+
WasmI32.sub(0n, cmpRational(y, x, totalOrdering))
|
|
1985
|
+
},
|
|
1986
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1987
|
+
WasmI32.sub(0n, cmpFloat(y, x, false, totalOrdering))
|
|
1988
|
+
},
|
|
1989
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1990
|
+
WasmI32.sub(0n, cmpFloat(y, x, true, totalOrdering))
|
|
1991
|
+
},
|
|
1992
|
+
_ => {
|
|
1993
|
+
throw UnknownNumberTag
|
|
1994
|
+
},
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
} else {
|
|
1998
|
+
let xBoxedNumberTag = boxedNumberTag(x)
|
|
1999
|
+
match (xBoxedNumberTag) {
|
|
2000
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
2001
|
+
cmpSmallInt(x, y, false, totalOrdering)
|
|
2002
|
+
},
|
|
2003
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
2004
|
+
cmpSmallInt(x, y, true, totalOrdering)
|
|
2005
|
+
},
|
|
2006
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
2007
|
+
cmpBigInt(x, y)
|
|
2008
|
+
},
|
|
2009
|
+
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
2010
|
+
cmpRational(x, y, totalOrdering)
|
|
2011
|
+
},
|
|
2012
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
2013
|
+
cmpFloat(x, y, false, totalOrdering)
|
|
2014
|
+
},
|
|
2015
|
+
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
2016
|
+
cmpFloat(x, y, true, totalOrdering)
|
|
2017
|
+
},
|
|
2018
|
+
_ => {
|
|
2019
|
+
throw UnknownNumberTag
|
|
2020
|
+
},
|
|
1795
2021
|
}
|
|
1796
2022
|
}
|
|
1797
2023
|
}
|
|
1798
2024
|
|
|
2025
|
+
@unsafe
|
|
2026
|
+
export let (<) = (x: Number, y: Number) => {
|
|
2027
|
+
let x = WasmI32.fromGrain(x)
|
|
2028
|
+
let y = WasmI32.fromGrain(y)
|
|
2029
|
+
WasmI32.ltS(cmp(x, y, false), 0n)
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
@unsafe
|
|
2033
|
+
export let (>) = (x: Number, y: Number) => {
|
|
2034
|
+
let x = WasmI32.fromGrain(x)
|
|
2035
|
+
let y = WasmI32.fromGrain(y)
|
|
2036
|
+
WasmI32.gtS(cmp(x, y, false), 0n)
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
@unsafe
|
|
2040
|
+
export let (<=) = (x: Number, y: Number) => {
|
|
2041
|
+
let x = WasmI32.fromGrain(x)
|
|
2042
|
+
let y = WasmI32.fromGrain(y)
|
|
2043
|
+
WasmI32.leS(cmp(x, y, false), 0n)
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
@unsafe
|
|
2047
|
+
export let (>=) = (x: Number, y: Number) => {
|
|
2048
|
+
let x = WasmI32.fromGrain(x)
|
|
2049
|
+
let y = WasmI32.fromGrain(y)
|
|
2050
|
+
WasmI32.geS(cmp(x, y, false), 0n)
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
@unsafe
|
|
2054
|
+
export let compare = (x: Number, y: Number) => {
|
|
2055
|
+
let x = WasmI32.fromGrain(x)
|
|
2056
|
+
let y = WasmI32.fromGrain(y)
|
|
2057
|
+
WasmI32.toGrain(tagSimple(cmp(x, y, true))): Number
|
|
2058
|
+
}
|
|
2059
|
+
|
|
1799
2060
|
/*
|
|
1800
2061
|
* ===== EQUAL =====
|
|
1801
2062
|
*/
|
|
@@ -1811,7 +2072,7 @@ export let numberEq = (x: Number, y: Number) => {
|
|
|
1811
2072
|
* ===== LOGICAL OPERATIONS =====
|
|
1812
2073
|
* Only valid for int-like numbers. Coerce to i64/bigInt and do operations
|
|
1813
2074
|
*/
|
|
1814
|
-
// TODO
|
|
2075
|
+
// TODO(#306): Semantics around when things should stay i32/i64
|
|
1815
2076
|
|
|
1816
2077
|
@unsafe
|
|
1817
2078
|
export let lnot = (x: Number) => {
|
|
@@ -1833,7 +2094,15 @@ export let (<<) = (x: Number, y: Number) => {
|
|
|
1833
2094
|
} else {
|
|
1834
2095
|
let xval = coerceNumberToWasmI64(x)
|
|
1835
2096
|
let yval = coerceNumberToWasmI64(y)
|
|
1836
|
-
|
|
2097
|
+
// if the number will be shifted beyond the end of the i64 range, promote to BigInt
|
|
2098
|
+
// (note that we subtract one leading zero, since the leading bit is the sign bit)
|
|
2099
|
+
if (WasmI64.leU(WasmI64.sub(WasmI64.clz(i64abs(xval)), 1N), yval)) {
|
|
2100
|
+
let xbi = coerceNumberToBigInt(x)
|
|
2101
|
+
let yval = coerceNumberToWasmI32(y)
|
|
2102
|
+
WasmI32.toGrain(reducedBigInteger(BI.shl(xbi, yval))): Number
|
|
2103
|
+
} else {
|
|
2104
|
+
WasmI32.toGrain(reducedInteger(WasmI64.shl(xval, yval))): Number
|
|
2105
|
+
}
|
|
1837
2106
|
}
|
|
1838
2107
|
}
|
|
1839
2108
|
|
|
@@ -2220,3 +2489,57 @@ export let isBigInt = x => {
|
|
|
2220
2489
|
let x = WasmI32.fromGrain(x)
|
|
2221
2490
|
isBigInt(x)
|
|
2222
2491
|
}
|
|
2492
|
+
|
|
2493
|
+
// Scalbn is based on https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c
|
|
2494
|
+
/*
|
|
2495
|
+
* ====================================================
|
|
2496
|
+
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
2497
|
+
*
|
|
2498
|
+
* Permission to use, copy, modify, and distribute this
|
|
2499
|
+
* software is freely granted, provided that this notice
|
|
2500
|
+
* is preserved.
|
|
2501
|
+
* ====================================================
|
|
2502
|
+
*/
|
|
2503
|
+
/**
|
|
2504
|
+
* Multiplies a floating-point number by an integral power of 2.
|
|
2505
|
+
*
|
|
2506
|
+
* @param x: The floating-point value
|
|
2507
|
+
* @param n: The Integer exponent
|
|
2508
|
+
* @returns The result of x * 2^n
|
|
2509
|
+
*
|
|
2510
|
+
* @since v0.5.4
|
|
2511
|
+
*/
|
|
2512
|
+
@unsafe
|
|
2513
|
+
export let scalbn = (x, n) => {
|
|
2514
|
+
let (>) = WasmI32.gtS
|
|
2515
|
+
let (<) = WasmI32.ltS
|
|
2516
|
+
let (*) = WasmF64.mul
|
|
2517
|
+
let (-) = WasmI32.sub
|
|
2518
|
+
let (+) = WasmI32.add
|
|
2519
|
+
let (<<) = WasmI64.shl
|
|
2520
|
+
// Constants
|
|
2521
|
+
let const_0x1p1023 = 8.98847e+307W
|
|
2522
|
+
let const_0x1p_1022 = 2.22507e-308W
|
|
2523
|
+
let const_0x1p53 = 9.0072e+15W
|
|
2524
|
+
let mut n = n
|
|
2525
|
+
let mut y = x
|
|
2526
|
+
if (n > 1023n) {
|
|
2527
|
+
y *= const_0x1p1023
|
|
2528
|
+
n -= 1023n
|
|
2529
|
+
if (n > 1023n) {
|
|
2530
|
+
y *= const_0x1p1023
|
|
2531
|
+
n -= 1023n
|
|
2532
|
+
if (n > 1023n) n = 1023n
|
|
2533
|
+
} else if (n < -1023n) {
|
|
2534
|
+
/* make sure final n < -53 to avoid double rounding in the subnormal range */
|
|
2535
|
+
y *= const_0x1p_1022 * const_0x1p53
|
|
2536
|
+
n += 1022n - 53n
|
|
2537
|
+
if (n < -1022n) {
|
|
2538
|
+
y *= const_0x1p_1022 * const_0x1p53
|
|
2539
|
+
n += 1022n - 53n
|
|
2540
|
+
if (n < -1022n) n = -1022n
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
y * WasmF64.reinterpretI64(WasmI64.extendI32S(0x3FFn + n) << 52N)
|
|
2545
|
+
}
|