@grain/stdlib 0.6.6 → 0.7.1

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 +67 -0
  2. package/LICENSE +1 -1
  3. package/README.md +2 -2
  4. package/array.gr +55 -7
  5. package/array.md +606 -560
  6. package/bigint.md +228 -228
  7. package/buffer.gr +85 -53
  8. package/buffer.md +442 -319
  9. package/bytes.gr +112 -35
  10. package/bytes.md +299 -219
  11. package/char.gr +201 -99
  12. package/char.md +447 -120
  13. package/exception.gr +11 -11
  14. package/exception.md +29 -4
  15. package/float32.gr +327 -3
  16. package/float32.md +698 -111
  17. package/float64.gr +320 -3
  18. package/float64.md +698 -111
  19. package/fs.gr +1082 -0
  20. package/fs.md +630 -0
  21. package/hash.gr +142 -88
  22. package/hash.md +105 -17
  23. package/int16.md +178 -178
  24. package/int32.gr +26 -5
  25. package/int32.md +266 -231
  26. package/int64.gr +27 -2
  27. package/int64.md +266 -231
  28. package/int8.md +178 -178
  29. package/json.gr +366 -51
  30. package/json.md +431 -15
  31. package/list.gr +328 -31
  32. package/list.md +759 -336
  33. package/map.gr +20 -12
  34. package/map.md +266 -260
  35. package/marshal.gr +41 -40
  36. package/marshal.md +14 -14
  37. package/number.gr +278 -35
  38. package/number.md +688 -269
  39. package/option.md +162 -162
  40. package/package.json +5 -3
  41. package/path.gr +48 -0
  42. package/path.md +180 -89
  43. package/pervasives.gr +2 -2
  44. package/pervasives.md +275 -275
  45. package/priorityqueue.gr +7 -7
  46. package/priorityqueue.md +131 -131
  47. package/queue.gr +183 -29
  48. package/queue.md +404 -148
  49. package/random.md +43 -43
  50. package/range.gr +4 -4
  51. package/range.md +42 -42
  52. package/rational.md +123 -123
  53. package/regex.gr +52 -51
  54. package/regex.md +102 -102
  55. package/result.md +118 -118
  56. package/runtime/atof/common.md +39 -39
  57. package/runtime/atof/decimal.gr +6 -6
  58. package/runtime/atof/decimal.md +14 -14
  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 +8 -8
  71. package/runtime/dataStructures.md +211 -211
  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 +8 -8
  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 +13 -13
  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 +348 -342
  98. package/runtime/string.gr +37 -105
  99. package/runtime/string.md +20 -26
  100. package/runtime/unsafe/constants.md +24 -24
  101. package/runtime/unsafe/conv.md +19 -19
  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 +147 -147
  117. package/set.gr +18 -11
  118. package/set.md +253 -247
  119. package/stack.gr +171 -2
  120. package/stack.md +371 -89
  121. package/string.gr +352 -557
  122. package/string.md +298 -255
  123. package/uint16.md +170 -170
  124. package/uint32.gr +25 -4
  125. package/uint32.md +249 -214
  126. package/uint64.gr +25 -5
  127. package/uint64.md +249 -214
  128. package/uint8.md +170 -170
  129. package/uri.gr +57 -53
  130. package/uri.md +88 -89
  131. package/wasi/file.gr +67 -59
  132. package/wasi/file.md +308 -308
  133. package/wasi/process.md +26 -26
  134. package/wasi/random.md +12 -12
  135. package/wasi/time.md +16 -16
  136. package/runtime/utils/printing.gr +0 -60
  137. package/runtime/utils/printing.md +0 -26
package/runtime/gc.gr CHANGED
@@ -21,21 +21,20 @@ module GC
21
21
 
22
22
  from "runtime/malloc" include Malloc
23
23
  from "runtime/unsafe/tags" include Tags
24
+ from "runtime/unsafe/panic" include Panic
24
25
  from "runtime/unsafe/wasmi32" include WasmI32
25
26
  use WasmI32.{ (+), (-), (*), (&), (==), (!=) }
26
27
 
27
- // Using foreigns directly here to avoid cyclic dependency
28
- foreign wasm fd_write:
29
- (WasmI32, WasmI32, WasmI32, WasmI32) => WasmI32 from "wasi_snapshot_preview1"
30
-
28
+ primitive (!) = "@not"
31
29
  primitive (&&) = "@and"
32
30
  primitive (||) = "@or"
33
- primitive throw = "@throw"
34
31
  primitive ignore = "@ignore"
35
32
  primitive box = "@box"
36
33
  primitive unbox = "@unbox"
37
34
 
38
- exception DecRefError
35
+ let throwDecRefError = () => {
36
+ Panic.panic("DecRefError: Reference count of zero")
37
+ }
39
38
 
40
39
  let mut _DEBUG = false
41
40
 
@@ -86,24 +85,37 @@ let rec decRef = (userPtr: WasmI32, ignoreZeros: Bool) => {
86
85
  // }
87
86
 
88
87
  if (WasmI32.eqz(refCount)) {
89
- if (ignoreZeros) {
90
- userPtr
91
- } else {
92
- throw DecRefError
88
+ if (!ignoreZeros) {
89
+ throwDecRefError()
93
90
  }
94
91
  } else {
95
92
  let refCount = refCount - 1n
96
93
  setRefCount(userPtr, refCount)
97
94
 
98
95
  if (WasmI32.eqz(refCount)) {
99
- decRefChildren(userPtr)
96
+ /*
97
+ * Note: We call free before decRefChildren to allow for a tail call.
98
+ * This is okay because no allocations occur while we traverse the
99
+ * structure and free does not mangle the data.
100
+ */
100
101
  free(userPtr)
102
+ decRefChildren(userPtr)
101
103
  }
102
-
103
- userPtr
104
104
  }
105
- } else {
106
- userPtr
105
+ }
106
+ }
107
+ and decRefChildrenHelp = (
108
+ userPtr: WasmI32,
109
+ arityOffset: WasmI32,
110
+ offset: WasmI32,
111
+ ) => {
112
+ let arity = WasmI32.load(userPtr, arityOffset)
113
+ if (arity != 0n) {
114
+ let maxOffset = (arity - 1n) * 4n
115
+ for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
116
+ decRef(WasmI32.load(userPtr + i, offset), false)
117
+ }
118
+ decRef(WasmI32.load(userPtr + maxOffset, offset), false)
107
119
  }
108
120
  }
109
121
  and decRefChildren = (userPtr: WasmI32) => {
@@ -112,43 +124,25 @@ and decRefChildren = (userPtr: WasmI32) => {
112
124
  let tag = WasmI32.load(userPtr, 4n)
113
125
  if (userPtr == Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) {
114
126
  // decRef underlying BigInts
115
- ignore(decRef(WasmI32.load(userPtr, 8n), false))
116
- ignore(decRef(WasmI32.load(userPtr, 12n), false))
127
+ decRef(WasmI32.load(userPtr, 8n), false)
128
+ decRef(WasmI32.load(userPtr, 12n), false)
117
129
  }
118
130
  },
119
131
  t when t == Tags._GRAIN_ADT_HEAP_TAG => {
120
- let arity = WasmI32.load(userPtr, 16n)
121
- let maxOffset = arity * 4n
122
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
123
- ignore(decRef(WasmI32.load(userPtr + i, 20n), false))
124
- }
132
+ decRefChildrenHelp(userPtr, 16n, 20n)
125
133
  },
126
- t when t == Tags._GRAIN_RECORD_HEAP_TAG => {
127
- let arity = WasmI32.load(userPtr, 12n)
128
- let maxOffset = arity * 4n
129
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
130
- ignore(decRef(WasmI32.load(userPtr + i, 16n), false))
131
- }
134
+ t when t == Tags._GRAIN_RECORD_HEAP_TAG || t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
135
+ decRefChildrenHelp(userPtr, 12n, 16n)
132
136
  },
133
137
  t when t == Tags._GRAIN_ARRAY_HEAP_TAG || t == Tags._GRAIN_TUPLE_HEAP_TAG => {
134
- let arity = WasmI32.load(userPtr, 4n)
135
- let maxOffset = arity * 4n
136
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
137
- ignore(decRef(WasmI32.load(userPtr + i, 8n), false))
138
- }
139
- },
140
- t when t == Tags._GRAIN_LAMBDA_HEAP_TAG => {
141
- let arity = WasmI32.load(userPtr, 12n)
142
- let maxOffset = arity * 4n
143
- for (let mut i = 0n; WasmI32.ltU(i, maxOffset); i += 4n) {
144
- ignore(decRef(WasmI32.load(userPtr + i, 16n), false))
145
- }
146
- },
147
- _ => {
148
- // No travelsal necessary for other tags
149
- void
138
+ decRefChildrenHelp(userPtr, 4n, 8n)
150
139
  },
140
+ // No traversal necessary for other tags
141
+ _ => void,
151
142
  }
152
143
  }
153
144
 
154
- provide let decRef = userPtr => decRef(userPtr, false)
145
+ provide let decRef = userPtr => {
146
+ decRef(userPtr, false)
147
+ userPtr
148
+ }
package/runtime/gc.md CHANGED
@@ -9,24 +9,24 @@ Functions and constants included in the GC module.
9
9
  ### GC.**malloc**
10
10
 
11
11
  ```grain
12
- malloc : (size: WasmI32) => WasmI32
12
+ malloc: (size: WasmI32) => WasmI32
13
13
  ```
14
14
 
15
15
  ### GC.**free**
16
16
 
17
17
  ```grain
18
- free : (userPtr: WasmI32) => Void
18
+ free: (userPtr: WasmI32) => Void
19
19
  ```
20
20
 
21
21
  ### GC.**incRef**
22
22
 
23
23
  ```grain
24
- incRef : (userPtr: WasmI32) => WasmI32
24
+ incRef: (userPtr: WasmI32) => WasmI32
25
25
  ```
26
26
 
27
27
  ### GC.**decRef**
28
28
 
29
29
  ```grain
30
- decRef : (userPtr: WasmI32) => WasmI32
30
+ decRef: (userPtr: WasmI32) => WasmI32
31
31
  ```
32
32
 
package/runtime/malloc.gr CHANGED
@@ -21,7 +21,7 @@ use WasmI32.{
21
21
  (&),
22
22
  (^),
23
23
  }
24
- from "runtime/exception" include Exception
24
+ from "runtime/unsafe/panic" include Panic
25
25
 
26
26
  primitive memorySize = "@wasm.memory_size"
27
27
  primitive memoryGrow = "@wasm.memory_grow"
@@ -38,12 +38,12 @@ primitive heapStart = "@heap.start"
38
38
  * lists are maintained, one for small blocks of 64 bytes, and one for larger
39
39
  * blocks of multiples of 64 bytes. Each block has an 8-byte header and 8-byte
40
40
  * footer to keep track of block sizes and maintain the free list.
41
- *
41
+ *
42
42
  * Most allocations in programs are small, so the separate free lists allow us
43
43
  * to implement `malloc` and `free` in O(1) for small allocations and O(n)
44
44
  * `malloc` and O(1) `free` for large allocations, where `n` is the size of the
45
45
  * free list for large blocks.
46
- *
46
+ *
47
47
  * The small blocks are able to service:
48
48
  * - Numbers (with the exception of large BigInts/Rationals)
49
49
  * - Tuples/Arrays up to 8 elements
@@ -51,7 +51,7 @@ primitive heapStart = "@heap.start"
51
51
  * - Variants up to 5 elements
52
52
  * - Closures up to 6 elements
53
53
  * - Bytes/Strings up to length 32
54
- *
54
+ *
55
55
  * Blocks in memory look like this:
56
56
  *
57
57
  * 8 bytes 8 bytes 64n - 16 bytes 8 bytes 8 bytes
@@ -71,11 +71,11 @@ primitive heapStart = "@heap.start"
71
71
  *
72
72
  * The size is kept in the header and footer to allow us to quickly combine
73
73
  * free blocks when blocks are freed.
74
- *
74
+ *
75
75
  * Pointers to the previous/next free blocks give us doubly-linked free lists,
76
76
  * which makes it possible to remove blocks from the free list in constant
77
77
  * time.
78
- *
78
+ *
79
79
  * A block is considered in use when the previous/next pointers are both zero.
80
80
  */
81
81
 
@@ -329,7 +329,7 @@ let morecore = (nunits: WasmI32) => {
329
329
 
330
330
  // If there was an error, fail
331
331
  if (cp == -1n) {
332
- Exception.panic("OutOfMemory: Maximum memory size exceeded")
332
+ Panic.panic("OutOfMemory: Maximum memory size exceeded")
333
333
  } else {
334
334
  // Set up the block. We'll add dummy headers/footers before and after the
335
335
  // block to avoid unnecessary bounds checks elsewhere in the code.
package/runtime/malloc.md CHANGED
@@ -9,47 +9,47 @@ Functions and constants included in the Malloc module.
9
9
  ### Malloc.**_RESERVED_RUNTIME_SPACE**
10
10
 
11
11
  ```grain
12
- _RESERVED_RUNTIME_SPACE : WasmI32
12
+ _RESERVED_RUNTIME_SPACE: WasmI32
13
13
  ```
14
14
 
15
15
  ### Malloc.**free**
16
16
 
17
17
  ```grain
18
- free : (ap: WasmI32) => Void
18
+ free: (ap: WasmI32) => Void
19
19
  ```
20
20
 
21
21
  Frees the given allocated pointer.
22
22
 
23
23
  Parameters:
24
24
 
25
- |param|type|description|
26
- |-----|----|-----------|
27
- |`ap`|`WasmI32`|The pointer to free|
25
+ | param | type | description |
26
+ | ----- | --------- | ------------------- |
27
+ | `ap` | `WasmI32` | The pointer to free |
28
28
 
29
29
  ### Malloc.**malloc**
30
30
 
31
31
  ```grain
32
- malloc : (nbytes: WasmI32) => WasmI32
32
+ malloc: (nbytes: WasmI32) => WasmI32
33
33
  ```
34
34
 
35
35
  Allocates the requested number of bytes, returning a pointer.
36
36
 
37
37
  Parameters:
38
38
 
39
- |param|type|description|
40
- |-----|----|-----------|
41
- |`nbytes`|`WasmI32`|The number of bytes to allocate|
39
+ | param | type | description |
40
+ | -------- | --------- | ------------------------------- |
41
+ | `nbytes` | `WasmI32` | The number of bytes to allocate |
42
42
 
43
43
  Returns:
44
44
 
45
- |type|description|
46
- |----|-----------|
47
- |`WasmI32`|The pointer to the allocated region (8-byte aligned) or -1 if the allocation failed|
45
+ | type | description |
46
+ | --------- | ----------------------------------------------------------------------------------- |
47
+ | `WasmI32` | The pointer to the allocated region (8-byte aligned) or -1 if the allocation failed |
48
48
 
49
49
  ### Malloc.**leakAll**
50
50
 
51
51
  ```grain
52
- leakAll : () => Void
52
+ leakAll: () => Void
53
53
  ```
54
54
 
55
55
  Leaks all memory in all free lists; used for testing.
@@ -0,0 +1,70 @@
1
+ /*
2
+ * ====================================================
3
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4
+ *
5
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
6
+ * Permission to use, copy, modify, and distribute this
7
+ * software is freely granted, provided that this notice
8
+ * is preserved.
9
+ * ====================================================
10
+ */
11
+ module Cosine
12
+
13
+ from "runtime/unsafe/wasmf64" include WasmF64
14
+
15
+ /*
16
+ * Source: https://git.musl-libc.org/cgit/musl/tree/src/math/__cos.c
17
+ *
18
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
19
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
20
+ * Input y is the tail of x.
21
+ *
22
+ * Algorithm
23
+ * 1. Since cos(-x) = cos(x), we need only to consider positive x.
24
+ * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
25
+ * 3. cos(x) is approximated by a polynomial of degree 14 on
26
+ * [0,pi/4]
27
+ * 4 14
28
+ * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
29
+ * where the remez error is
30
+ *
31
+ * | 2 4 6 8 10 12 14 | -58
32
+ * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
33
+ * | |
34
+ *
35
+ * 4 6 8 10 12 14
36
+ * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
37
+ * cos(x) ~ 1 - x*x/2 + r
38
+ * since cos(x+y) ~ cos(x) - sin(x)*y
39
+ * ~ cos(x) - x*y,
40
+ * a correction term is necessary in cos(x) and hence
41
+ * cos(x+y) = 1 - (x*x/2 - (r - x*y))
42
+ * For better accuracy, rearrange to
43
+ * cos(x+y) ~ w + (tmp + (r-x*y))
44
+ * where w = 1 - x*x/2 and tmp is a tiny correction term
45
+ * (1 - x*x/2 == w + tmp exactly in infinite precision).
46
+ * The exactness of w + tmp in infinite precision depends on w
47
+ * and tmp having the same precision as x. If they have extra
48
+ * precision due to compiler bugs, then the extra precision is
49
+ * only good provided it is retained in all terms of the final
50
+ * expression for cos(). Retention happens in all cases tested
51
+ * under FreeBSD, so don't pessimize things by forcibly clipping
52
+ * any extra precision in w.
53
+ */
54
+ @unsafe
55
+ provide let cos = (x: WasmF64, y: WasmF64) => {
56
+ use WasmF64.{ (+), (-), (*) }
57
+ let c1 = 4.16666666666666019037e-02W /* 0x3FA55555, 0x5555554C */
58
+ let c2 = -1.38888888888741095749e-03W /* 0xBF56C16C, 0x16C15177 */
59
+ let c3 = 2.48015872894767294178e-05W /* 0x3EFA01A0, 0x19CB1590 */
60
+ let c4 = -2.75573143513906633035e-07W /* 0xBE927E4F, 0x809C52AD */
61
+ let c5 = 2.08757232129817482790e-09W /* 0x3E21EE9E, 0xBDB4B1C4 */
62
+ let c6 = -1.13596475577881948265e-11W /* 0xBDA8FAE9, 0xBE8838D4 */
63
+
64
+ let z = x * x
65
+ let w = z * z
66
+ let r = z * (c1 + z * (c2 + z * c3)) + w * w * (c4 + z * (c5 + z * c6))
67
+ let hz = 0.5W * z
68
+ let w = 1.0W - hz
69
+ w + (1.0W - w - hz + (z * r - x * y))
70
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Cosine
3
+ ---
4
+
5
+ ## Values
6
+
7
+ Functions and constants included in the Cosine module.
8
+
9
+ ### Cosine.**cos**
10
+
11
+ ```grain
12
+ cos: (x: WasmF64, y: WasmF64) => WasmF64
13
+ ```
14
+
@@ -0,0 +1,65 @@
1
+ /*
2
+ * ====================================================
3
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4
+ *
5
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
6
+ * Permission to use, copy, modify, and distribute this
7
+ * software is freely granted, provided that this notice
8
+ * is preserved.
9
+ * ====================================================
10
+ */
11
+ module Sine
12
+
13
+ from "runtime/unsafe/wasmf64" include WasmF64
14
+
15
+ /*
16
+ * Source: https://git.musl-libc.org/cgit/musl/tree/src/math/__sin.c
17
+ *
18
+ * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
19
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
20
+ * Input y is the tail of x.
21
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
22
+ *
23
+ * Algorithm
24
+ * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
25
+ * 2. Callers must return sin(-0) = -0 without calling here since our
26
+ * odd polynomial is not evaluated in a way that preserves -0.
27
+ * Callers may do the optimization sin(x) ~ x for tiny x.
28
+ * 3. sin(x) is approximated by a polynomial of degree 13 on
29
+ * [0,pi/4]
30
+ * 3 13
31
+ * sin(x) ~ x + S1*x + ... + S6*x
32
+ * where
33
+ *
34
+ * |sin(x) 2 4 6 8 10 12 | -58
35
+ * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
36
+ * | x |
37
+ *
38
+ * 4. sin(x+y) = sin(x) + sin'(x')*y
39
+ * ~ sin(x) + (1-x*x/2)*y
40
+ * For better accuracy, let
41
+ * 3 2 2 2 2
42
+ * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
43
+ * then 3 2
44
+ * sin(x) = x + (S1*x + (x *(r-y/2)+y))
45
+ */
46
+ @unsafe
47
+ provide let sin = (x: WasmF64, y: WasmF64, iy: Bool) => { // see: musl/tree/src/math/__sin.c
48
+ use WasmF64.{ (+), (-), (*) }
49
+ let s1 = -1.66666666666666324348e-01W /* 0xBFC55555, 0x55555549 */
50
+ let s2 = 8.33333333332248946124e-03W /* 0x3F811111, 0x1110F8A6 */
51
+ let s3 = -1.98412698298579493134e-04W /* 0xBF2A01A0, 0x19C161D5 */
52
+ let s4 = 2.75573137070700676789e-06W /* 0x3EC71DE3, 0x57B1FE7D */
53
+ let s5 = -2.50507602534068634195e-08W /* 0xBE5AE5E6, 0x8A2B9CEB */
54
+ let s6 = 1.58969099521155010221e-10W /* 0x3DE5D93A, 0x5ACFD57C */
55
+
56
+ let z = x * x
57
+ let w = z * z
58
+ let r = s2 + z * (s3 + z * s4) + z * w * (s5 + z * s6)
59
+ let v = z * x
60
+ if (!iy) {
61
+ x + v * (s1 + z * r)
62
+ } else {
63
+ x - (z * (0.5W * y - v * r) - y - v * s1)
64
+ }
65
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Sine
3
+ ---
4
+
5
+ ## Values
6
+
7
+ Functions and constants included in the Sine module.
8
+
9
+ ### Sine.**sin**
10
+
11
+ ```grain
12
+ sin: (x: WasmF64, y: WasmF64, iy: Bool) => WasmF64
13
+ ```
14
+
@@ -0,0 +1,136 @@
1
+ /*
2
+ * ====================================================
3
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4
+ *
5
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
6
+ * Permission to use, copy, modify, and distribute this
7
+ * software is freely granted, provided that this notice
8
+ * is preserved.
9
+ * ====================================================
10
+ */
11
+ module Tangent
12
+
13
+ from "runtime/unsafe/wasmi32" include WasmI32
14
+ from "runtime/unsafe/wasmi64" include WasmI64
15
+ from "runtime/unsafe/wasmf64" include WasmF64
16
+
17
+ /*
18
+ * Source: lib/msun/src/k_tan.c
19
+ *
20
+ * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
21
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
22
+ * Input y is the tail of x.
23
+ * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
24
+ *
25
+ * Algorithm
26
+ * 1. Since tan(-x) = -tan(x), we need only to consider positive x.
27
+ * 2. Callers must return tan(-0) = -0 without calling here since our
28
+ * odd polynomial is not evaluated in a way that preserves -0.
29
+ * Callers may do the optimization tan(x) ~ x for tiny x.
30
+ * 3. tan(x) is approximated by a odd polynomial of degree 27 on
31
+ * [0,0.67434]
32
+ * 3 27
33
+ * tan(x) ~ x + T1*x + ... + T13*x
34
+ * where
35
+ *
36
+ * |tan(x) 2 4 26 | -59.2
37
+ * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
38
+ * | x |
39
+ *
40
+ * Note: tan(x+y) = tan(x) + tan'(x)*y
41
+ * ~ tan(x) + (1+x*x)*y
42
+ * Therefore, for better accuracy in computing tan(x+y), let
43
+ * 3 2 2 2 2
44
+ * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
45
+ * then
46
+ * 3 2
47
+ * tan(x+y) = x + (T1*x + (x *(r+y)+y))
48
+ *
49
+ * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
50
+ * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
51
+ * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
52
+ */
53
+ @unsafe
54
+ provide let tan = (x: WasmF64, y: WasmF64, iy: Bool) => {
55
+ use WasmI32.{ (&), (>>), (<), (>=) }
56
+ use WasmI64.{ (>>>) }
57
+ use WasmF64.{ (-), (+), (*), (/) }
58
+ let t0 = 3.33333333333334091986e-01W /* 3FD55555, 55555563 */
59
+ let t1 = 1.33333333333201242699e-01W /* 3FC11111, 1110FE7A */
60
+ let t2 = 5.39682539762260521377e-02W /* 3FABA1BA, 1BB341FE */
61
+ let t3 = 2.18694882948595424599e-02W /* 3F9664F4, 8406D637 */
62
+ let t4 = 8.86323982359930005737e-03W /* 3F8226E3, E96E8493 */
63
+ let t5 = 3.59207910759131235356e-03W /* 3F6D6D22, C9560328 */
64
+ let t6 = 1.45620945432529025516e-03W /* 3F57DBC8, FEE08315 */
65
+ let t7 = 5.88041240820264096874e-04W /* 3F4344D8, F2F26501 */
66
+ let t8 = 2.46463134818469906812e-04W /* 3F3026F7, 1A8D1068 */
67
+ let t9 = 7.81794442939557092300e-05W /* 3F147E88, A03792A6 */
68
+ let t10 = 7.14072491382608190305e-05W /* 3F12B80F, 32F0A7E9 */
69
+ let t11 = -1.85586374855275456654e-05W /* BEF375CB, DB605373 */
70
+ let t12 = 2.59073051863633712884e-05W /* 3EFB2A70, 74BF7AD4 */
71
+ let pio4 = 7.85398163397448278999e-01W /* 3FE921FB, 54442D18 */
72
+ let pio4lo = 3.06161699786838301793e-17W /* 3C81A626, 33145C07 */
73
+
74
+ let mut x = x
75
+ let mut y = y
76
+ let mut z = 0.0W
77
+ let mut r = 0.0W
78
+ let mut w = 0.0W
79
+
80
+ let h = WasmI64.reinterpretF64(x)
81
+ let hx = WasmI32.wrapI64(h >>> 32N) // High word of {x}
82
+ let ix = hx & 0x7FFFFFFFn // High word of |x|
83
+
84
+ let isBig = ix >= 0x3FE59428n
85
+ if (isBig) { /* |x| >= 0.6744 */
86
+ if (hx < 0n) {
87
+ x *= -1.0W
88
+ y *= -1.0W
89
+ }
90
+ z = pio4 - x
91
+ w = pio4lo - y
92
+ x = z + w
93
+ y = 0.0W
94
+ }
95
+ z = x * x
96
+ w = z * z
97
+
98
+ /*
99
+ * Break x^5*(T[1]+x^2*T[2]+...) into
100
+ * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
101
+ * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
102
+ */
103
+ r = t1 + w * (t3 + w * (t5 + w * (t7 + w * (t9 + w * t11))))
104
+ let v = z * (t2 + w * (t4 + w * (t6 + w * (t8 + w * (t10 + w * t12)))))
105
+ let s = z * x
106
+ r = y + z * (s * (r + v) + y)
107
+ r += t0 * s
108
+ w = x + r
109
+ if (isBig) {
110
+ let v = if (iy) 1.0W else 0.0W
111
+ return 1.0W
112
+ - WasmF64.convertI32S(hx >> 30n & 2n)
113
+ * (v - 2.0W * (x - (w * w / (w + v) - r)))
114
+ }
115
+ if (iy) return w
116
+ /*
117
+ * if allow error up to 2 ulp, simply return
118
+ * -1.0 / (x+r) here
119
+ */
120
+ // compute -1.0 / (x+r) accurately
121
+ use WasmI64.{ (&) }
122
+ // Set low bits
123
+ let z = w
124
+ let z = WasmF64.reinterpretI64(
125
+ WasmI64.reinterpretF64(z) & 0xFFFFFFFF00000000N
126
+ )
127
+ let v = r - (z - x) // z + v = r + x
128
+ let a = -1.0W / w
129
+ let t = a
130
+ // Set low bits
131
+ let t = WasmF64.reinterpretI64(
132
+ WasmI64.reinterpretF64(t) & 0xFFFFFFFF00000000N
133
+ )
134
+ let s = 1.0W + t * z
135
+ return t + a * (s + t * v)
136
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Tangent
3
+ ---
4
+
5
+ ## Values
6
+
7
+ Functions and constants included in the Tangent module.
8
+
9
+ ### Tangent.**tan**
10
+
11
+ ```grain
12
+ tan: (x: WasmF64, y: WasmF64, iy: Bool) => WasmF64
13
+ ```
14
+