@grain/stdlib 0.6.6 → 0.7.0

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +1 -1
  3. package/README.md +2 -2
  4. package/array.gr +55 -7
  5. package/array.md +123 -77
  6. package/bigint.md +30 -30
  7. package/buffer.gr +20 -53
  8. package/buffer.md +47 -47
  9. package/bytes.gr +111 -35
  10. package/bytes.md +111 -32
  11. package/char.gr +201 -99
  12. package/char.md +361 -34
  13. package/exception.gr +11 -11
  14. package/exception.md +26 -1
  15. package/float32.gr +327 -3
  16. package/float32.md +606 -19
  17. package/float64.gr +320 -3
  18. package/float64.md +606 -19
  19. package/fs.gr +1082 -0
  20. package/fs.md +630 -0
  21. package/hash.gr +142 -88
  22. package/hash.md +102 -14
  23. package/int16.md +23 -23
  24. package/int32.gr +25 -4
  25. package/int32.md +65 -30
  26. package/int64.gr +26 -1
  27. package/int64.md +65 -30
  28. package/int8.md +23 -23
  29. package/json.gr +366 -51
  30. package/json.md +418 -2
  31. package/list.gr +328 -31
  32. package/list.md +492 -69
  33. package/map.gr +20 -12
  34. package/map.md +44 -38
  35. package/marshal.gr +41 -40
  36. package/marshal.md +2 -2
  37. package/number.gr +159 -30
  38. package/number.md +215 -38
  39. package/option.md +21 -21
  40. package/package.json +5 -3
  41. package/path.gr +48 -0
  42. package/path.md +103 -12
  43. package/pervasives.gr +2 -2
  44. package/pervasives.md +37 -37
  45. package/priorityqueue.gr +7 -7
  46. package/priorityqueue.md +19 -19
  47. package/queue.gr +183 -29
  48. package/queue.md +296 -40
  49. package/random.md +6 -6
  50. package/range.gr +4 -4
  51. package/range.md +6 -6
  52. package/rational.md +16 -16
  53. package/regex.gr +52 -51
  54. package/regex.md +11 -11
  55. package/result.md +16 -16
  56. package/runtime/atof/common.md +39 -39
  57. package/runtime/atof/decimal.gr +6 -6
  58. package/runtime/atof/decimal.md +8 -8
  59. package/runtime/atof/lemire.gr +5 -5
  60. package/runtime/atof/lemire.md +1 -1
  61. package/runtime/atof/parse.gr +16 -16
  62. package/runtime/atof/parse.md +2 -2
  63. package/runtime/atof/slow.md +1 -1
  64. package/runtime/atof/table.md +2 -2
  65. package/runtime/atoi/parse.gr +3 -3
  66. package/runtime/atoi/parse.md +1 -1
  67. package/runtime/bigint.gr +15 -47
  68. package/runtime/bigint.md +54 -60
  69. package/runtime/compare.gr +2 -2
  70. package/runtime/compare.md +1 -1
  71. package/runtime/dataStructures.md +33 -33
  72. package/runtime/debugPrint.gr +4 -1
  73. package/runtime/debugPrint.md +9 -9
  74. package/runtime/equal.gr +99 -77
  75. package/runtime/equal.md +1 -1
  76. package/runtime/exception.gr +62 -82
  77. package/runtime/exception.md +62 -11
  78. package/runtime/gc.gr +39 -45
  79. package/runtime/gc.md +4 -4
  80. package/runtime/malloc.gr +7 -7
  81. package/runtime/malloc.md +4 -4
  82. package/runtime/math/kernel/cos.gr +70 -0
  83. package/runtime/math/kernel/cos.md +14 -0
  84. package/runtime/math/kernel/sin.gr +65 -0
  85. package/runtime/math/kernel/sin.md +14 -0
  86. package/runtime/math/kernel/tan.gr +136 -0
  87. package/runtime/math/kernel/tan.md +14 -0
  88. package/runtime/math/rempio2.gr +244 -0
  89. package/runtime/math/rempio2.md +14 -0
  90. package/runtime/math/trig.gr +130 -0
  91. package/runtime/math/trig.md +28 -0
  92. package/runtime/math/umuldi.gr +26 -0
  93. package/runtime/math/umuldi.md +14 -0
  94. package/runtime/numberUtils.gr +29 -29
  95. package/runtime/numberUtils.md +12 -12
  96. package/runtime/numbers.gr +373 -381
  97. package/runtime/numbers.md +79 -73
  98. package/runtime/string.gr +37 -105
  99. package/runtime/string.md +3 -9
  100. package/runtime/unsafe/constants.md +24 -24
  101. package/runtime/unsafe/conv.md +13 -13
  102. package/runtime/unsafe/memory.gr +24 -20
  103. package/runtime/unsafe/memory.md +27 -7
  104. package/runtime/unsafe/offsets.gr +36 -0
  105. package/runtime/unsafe/offsets.md +88 -0
  106. package/runtime/unsafe/panic.gr +28 -0
  107. package/runtime/unsafe/panic.md +14 -0
  108. package/runtime/unsafe/tags.md +32 -32
  109. package/runtime/unsafe/wasmf32.md +28 -28
  110. package/runtime/unsafe/wasmf64.md +28 -28
  111. package/runtime/unsafe/wasmi32.md +47 -47
  112. package/runtime/unsafe/wasmi64.md +50 -50
  113. package/runtime/utf8.gr +189 -0
  114. package/runtime/utf8.md +117 -0
  115. package/runtime/wasi.gr +4 -2
  116. package/runtime/wasi.md +138 -138
  117. package/set.gr +18 -11
  118. package/set.md +42 -36
  119. package/stack.gr +171 -2
  120. package/stack.md +297 -15
  121. package/string.gr +352 -557
  122. package/string.md +77 -34
  123. package/uint16.md +22 -22
  124. package/uint32.gr +25 -4
  125. package/uint32.md +63 -28
  126. package/uint64.gr +25 -5
  127. package/uint64.md +63 -28
  128. package/uint8.md +22 -22
  129. package/uri.gr +57 -53
  130. package/uri.md +11 -12
  131. package/wasi/file.gr +67 -59
  132. package/wasi/file.md +39 -39
  133. package/wasi/process.md +5 -5
  134. package/wasi/random.md +3 -3
  135. package/wasi/time.md +4 -4
  136. package/runtime/utils/printing.gr +0 -60
  137. package/runtime/utils/printing.md +0 -26
package/number.gr CHANGED
@@ -48,6 +48,8 @@ from "runtime/atoi/parse" include Parse as Atoi
48
48
  from "runtime/atof/parse" include Parse as Atof
49
49
  from "runtime/unsafe/tags" include Tags
50
50
  from "runtime/exception" include Exception
51
+ from "runtime/math/trig" include Trig
52
+ use Trig.{ sin, cos, tan }
51
53
 
52
54
  use Atoi.{ type ParseIntError }
53
55
 
@@ -551,8 +553,8 @@ provide let isClose = (a, b, relativeTolerance=1e-9, absoluteTolerance=0.0) => {
551
553
  if (a == b) {
552
554
  true
553
555
  } else if (isFinite(a) && isFinite(b)) {
554
- abs(a - b) <=
555
- max(relativeTolerance * max(abs(a), abs(b)), absoluteTolerance)
556
+ abs(a - b)
557
+ <= max(relativeTolerance * max(abs(a), abs(b)), absoluteTolerance)
556
558
  } else {
557
559
  // NaN and infinities which were not equal
558
560
  false
@@ -659,28 +661,6 @@ provide let parse = input => {
659
661
  }
660
662
  }
661
663
 
662
- /**
663
- * Computes how many times pi has to be subtracted to achieve the required bounds for sin.
664
- */
665
- let reduceToPiBound = (radians: Number) => {
666
- floor(radians / pi)
667
- }
668
-
669
- /**
670
- * Computes the sine of a number using Chebyshev polynomials. Requires the input to be bounded to (-pi, pi). More information on the algorithm can be found here: http://mooooo.ooo/chebyshev-sine-approximation/.
671
- */
672
- let chebyshevSine = (radians: Number) => {
673
- let pi_minor = -0.00000008742278
674
- let x2 = radians * radians
675
- let p11 = 0.00000000013291342
676
- let p9 = p11 * x2 + -0.000000023317787
677
- let p7 = p9 * x2 + 0.0000025222919
678
- let p5 = p7 * x2 + -0.00017350505
679
- let p3 = p5 * x2 + 0.0066208798
680
- let p1 = p3 * x2 + -0.10132118
681
- (radians - pi - pi_minor) * (radians + pi + pi_minor) * p1 * radians
682
- }
683
-
684
664
  @unsafe
685
665
  let rf = z => {
686
666
  // see: musl/src/math/asin.c and SUN COPYRIGHT NOTICE at top of file
@@ -761,8 +741,8 @@ provide let asin = angle => {
761
741
  WasmI64.reinterpretF64(s) & 0xFFFFFFFF00000000N
762
742
  )
763
743
  let c = (z - f * f) / (s + f)
764
- x = 0.5W * pio2_hi -
765
- (2.0W * s * r - (pio2_lo - 2.0W * c) - (0.5W * pio2_hi - 2.0W * f))
744
+ x = 0.5W * pio2_hi
745
+ - (2.0W * s * r - (pio2_lo - 2.0W * c) - (0.5W * pio2_hi - 2.0W * f))
766
746
  }
767
747
  x = WasmF64.copySign(x, origAngle)
768
748
  return WasmI32.toGrain(newFloat64(x)): Number
@@ -1065,10 +1045,159 @@ provide let linearMap = (inputRange, outputRange, current) => {
1065
1045
  throw Exception.InvalidArgument("The outputRange must be finite")
1066
1046
  if (isNaN(outputRange.rangeStart) || isNaN(outputRange.rangeEnd))
1067
1047
  throw Exception.InvalidArgument("The outputRange must not include NaN")
1068
- let mapped = (current - inputRange.rangeStart) *
1069
- (outputRange.rangeEnd - outputRange.rangeStart) /
1070
- (inputRange.rangeEnd - inputRange.rangeStart) +
1071
- outputRange.rangeStart
1048
+ let mapped = (current - inputRange.rangeStart)
1049
+ * (outputRange.rangeEnd - outputRange.rangeStart)
1050
+ / (inputRange.rangeEnd - inputRange.rangeStart)
1051
+ + outputRange.rangeStart
1072
1052
  clamp(outputRange, mapped)
1073
1053
  }
1074
1054
  }
1055
+
1056
+ /**
1057
+ * Computes the sine of a number (in radians).
1058
+ *
1059
+ * @param radians: The input in radians
1060
+ * @returns The computed sine
1061
+ *
1062
+ * @example Number.sin(0) == 0
1063
+ *
1064
+ * @since v0.7.0
1065
+ */
1066
+ @unsafe
1067
+ provide let sin = (radians: Number) => {
1068
+ use WasmF64.{ (==) }
1069
+ let xval = coerceNumberToWasmF64(radians)
1070
+ let value = sin(xval)
1071
+ return if (!isFloat(radians) && value == WasmF64.trunc(value)) {
1072
+ WasmI32.toGrain(reducedInteger(WasmI64.truncF64S(value))): Number
1073
+ } else {
1074
+ WasmI32.toGrain(newFloat64(value)): Number
1075
+ }
1076
+ }
1077
+
1078
+ /**
1079
+ * Computes the cosine of a number (in radians).
1080
+ *
1081
+ * @param radians: The input in radians
1082
+ * @returns The computed cosine
1083
+ *
1084
+ * @example Number.cos(0) == 1
1085
+ *
1086
+ * @since v0.7.0
1087
+ */
1088
+ @unsafe
1089
+ provide let cos = (radians: Number) => {
1090
+ use WasmF64.{ (==) }
1091
+ let xval = coerceNumberToWasmF64(radians)
1092
+ let value = cos(xval)
1093
+ return if (!isFloat(radians) && value == WasmF64.trunc(value)) {
1094
+ WasmI32.toGrain(reducedInteger(WasmI64.truncF64S(value))): Number
1095
+ } else {
1096
+ WasmI32.toGrain(newFloat64(value)): Number
1097
+ }
1098
+ }
1099
+
1100
+ /**
1101
+ * Computes the tangent of a number (in radians).
1102
+ *
1103
+ * @param radians: The input in radians
1104
+ * @returns The computed tangent
1105
+ *
1106
+ * @example Number.tan(0) == 0
1107
+ *
1108
+ * @since v0.7.0
1109
+ */
1110
+ @unsafe
1111
+ provide let tan = (radians: Number) => {
1112
+ use WasmF64.{ (==) }
1113
+ let xval = coerceNumberToWasmF64(radians)
1114
+ let value = tan(xval)
1115
+ return if (!isFloat(radians) && value == WasmF64.trunc(value)) {
1116
+ WasmI32.toGrain(reducedInteger(WasmI64.truncF64S(value))): Number
1117
+ } else {
1118
+ WasmI32.toGrain(newFloat64(value)): Number
1119
+ }
1120
+ }
1121
+
1122
+ // Math.gamma implemented using the Lanczos approximation
1123
+ // https://en.wikipedia.org/wiki/Lanczos_approximation
1124
+ /**
1125
+ * Computes the gamma function of a value using the Lanczos approximation.
1126
+ *
1127
+ * @param z: The value to interpolate
1128
+ * @returns The gamma of the given value
1129
+ *
1130
+ * @example Number.gamma(1) == 1
1131
+ * @example Number.gamma(3) == 2
1132
+ * @example Number.isClose(Number.gamma(0.5), Number.sqrt(Number.pi))
1133
+ *
1134
+ * @since v0.7.0
1135
+ */
1136
+ provide let rec gamma = z => {
1137
+ if (z == 0 || isInteger(z) && z < 0) {
1138
+ NaN
1139
+ } else if (isInteger(z) && z > 0) {
1140
+ let mut output = 1
1141
+ for (let mut i = 1; i < z; i += 1) {
1142
+ output *= i
1143
+ }
1144
+ output
1145
+ } else {
1146
+ let mut z = z
1147
+ let g = 7
1148
+ let c = [>
1149
+ 0.99999999999980993,
1150
+ 676.5203681218851,
1151
+ -1259.1392167224028,
1152
+ 771.32342877765313,
1153
+ -176.61502916214059,
1154
+ 12.507343278686905,
1155
+ -0.13857109526572012,
1156
+ 9.9843695780195716e-6,
1157
+ 1.5056327351493116e-7,
1158
+ ]
1159
+ let mut output = 0
1160
+ if (z < 0.5) {
1161
+ output = pi / sin(pi * z) / gamma(1 - z)
1162
+ } else if (z == 0.5) {
1163
+ // Handle this case separately because it is out of the domain of Number.pow when calculating
1164
+ output = 1.7724538509055159
1165
+ } else {
1166
+ z -= 1
1167
+ let mut x = c[0]
1168
+ for (let mut i = 1; i < g + 2; i += 1) {
1169
+ x += c[i] / (z + i)
1170
+ }
1171
+
1172
+ let t = z + g + 0.5
1173
+ output = sqrt(2 * pi) * (t ** (z + 0.5)) * exp(t * -1) * x
1174
+ }
1175
+ if (abs(output) == Infinity) Infinity else output
1176
+ }
1177
+ }
1178
+
1179
+ /**
1180
+ * Computes the factorial of an integer input or the gamma function of a non-integer input.
1181
+ *
1182
+ * @param n: The value to factorialize
1183
+ * @returns The factorial of the given value
1184
+ *
1185
+ * @throws InvalidArgument(String): When `n` is a negative integer
1186
+ *
1187
+ * @example Number.factorial(0) == 1
1188
+ * @example Number.factorial(3) == 6
1189
+ * @example Number.isClose(Number.factorial(0.5), (1/2) * Number.sqrt(Number.pi))
1190
+ *
1191
+ * @since v0.7.0
1192
+ */
1193
+ provide let rec factorial = n => {
1194
+ if (isInteger(n) && n < 0) {
1195
+ gamma(abs(n) + 1) * -1
1196
+ } else if (!isInteger(n) && n < 0) {
1197
+ throw Exception.InvalidArgument(
1198
+ "Cannot compute the factorial of a negative non-integer",
1199
+ )
1200
+ } else {
1201
+ gamma(n + 1)
1202
+ }
1203
+ }