gofront 1.8.0 → 1.9.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 (178) hide show
  1. package/README.md +3 -3
  2. package/package.json +6 -5
  3. package/src/backend/js/expressions.js +1157 -408
  4. package/src/backend/js/index.js +327 -153
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +559 -2552
  7. package/src/backend/js/statements.js +670 -158
  8. package/src/backend/js/stdlib/index.js +45 -93
  9. package/src/backend/js/templ.js +32 -45
  10. package/src/backend/js/type-info.js +298 -19
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +91 -170
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +490 -965
  15. package/src/backend/wasm/emit-builtins.js +884 -256
  16. package/src/backend/wasm/emit-exprs.js +185 -77
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-shared.js +4 -1
  19. package/src/backend/wasm/emit-stmts.js +524 -240
  20. package/src/backend/wasm/emit.js +176 -38
  21. package/src/backend/wasm/globals.js +48 -8
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +44 -530
  24. package/src/backend/wasm/method-expr.js +12 -1
  25. package/src/backend/wasm/module-emitter.js +299 -770
  26. package/src/backend/wasm/monomorph.js +139 -8
  27. package/src/backend/wasm/natives.js +600 -0
  28. package/src/backend/wasm/prescan.js +5 -153
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -32
  31. package/src/backend/wasm/types.js +97 -20
  32. package/src/backend/wasm/variadic.js +9 -4
  33. package/src/cli/cli-core.js +5 -1
  34. package/src/cli/test-runner.js +115 -342
  35. package/src/compiler.js +113 -130
  36. package/src/lexer/lexer.js +106 -11
  37. package/src/lexer/templ-lexer.js +61 -18
  38. package/src/lexer/tokens.js +1 -0
  39. package/src/link/stdlib.js +355 -132
  40. package/src/link/type-names.js +204 -0
  41. package/src/link/wasm.js +30 -6
  42. package/src/lower/bounds.js +153 -0
  43. package/src/lower/captures.js +92 -33
  44. package/src/lower/embedding.js +62 -5
  45. package/src/lower/errors-as.js +196 -0
  46. package/src/lower/fmt-formatters.js +929 -0
  47. package/src/lower/functions.js +225 -7
  48. package/src/lower/gen-types.js +293 -0
  49. package/src/lower/index.js +14 -2
  50. package/src/lower/json-codecs.js +334 -245
  51. package/src/lower/ownership.js +25 -7
  52. package/src/lower/reachability.js +69 -51
  53. package/src/lower/walk.js +12 -0
  54. package/src/parser/declarations.js +30 -5
  55. package/src/parser/expressions.js +111 -57
  56. package/src/parser/statements.js +108 -0
  57. package/src/parser/templ.js +44 -5
  58. package/src/parser/types.js +12 -0
  59. package/src/resolver.js +1 -2
  60. package/src/typechecker/assignability.js +214 -19
  61. package/src/typechecker/const-fold.js +70 -27
  62. package/src/typechecker/constants.js +156 -8
  63. package/src/typechecker/expressions.js +490 -108
  64. package/src/typechecker/index.js +346 -42
  65. package/src/typechecker/init-order.js +136 -40
  66. package/src/typechecker/operand-text.js +41 -0
  67. package/src/typechecker/resolve.js +490 -65
  68. package/src/typechecker/statements.js +288 -27
  69. package/src/typechecker/stdlib/excluded.js +9 -5
  70. package/src/typechecker/stdlib/index.js +25 -9
  71. package/src/typechecker/termination.js +10 -1
  72. package/src/typechecker/types.js +287 -575
  73. package/stdlib/bytes/buffer.go +479 -0
  74. package/stdlib/bytes/bytes.go +1010 -0
  75. package/stdlib/bytes/reader.go +161 -0
  76. package/stdlib/context/context.go +115 -0
  77. package/stdlib/crypto/rand/rand.go +34 -0
  78. package/stdlib/crypto/sha256/sha256.go +249 -0
  79. package/stdlib/encoding/base64/base64.go +331 -0
  80. package/stdlib/encoding/binary/binary.go +332 -0
  81. package/stdlib/encoding/hex/hex.go +140 -0
  82. package/stdlib/encoding/json/json.go +62 -0
  83. package/stdlib/errors/errors.go +174 -0
  84. package/stdlib/fmt/errors.go +110 -0
  85. package/stdlib/fmt/format.go +732 -0
  86. package/stdlib/fmt/print.go +1232 -0
  87. package/stdlib/gom/gom.go +293 -0
  88. package/stdlib/html/html.go +251 -0
  89. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  90. package/stdlib/internal/jsonrt/dec.go +171 -38
  91. package/stdlib/internal/jsonrt/enc.go +186 -36
  92. package/stdlib/internal/jsonrt/scanner.go +17 -8
  93. package/stdlib/io/io.go +157 -1
  94. package/stdlib/maps/maps.go +131 -0
  95. package/stdlib/math/bits/bits.go +507 -0
  96. package/stdlib/math/extra.go +16 -14
  97. package/stdlib/math/math.go +439 -0
  98. package/stdlib/math/rand/rand.go +297 -0
  99. package/stdlib/os/os.go +93 -0
  100. package/stdlib/path/filepath/filepath.go +47 -0
  101. package/stdlib/path/path.go +394 -0
  102. package/stdlib/regexp/regexp.go +231 -0
  103. package/stdlib/slices/slices.go +526 -0
  104. package/stdlib/slices/sort.go +209 -0
  105. package/stdlib/slices/zsort_cmp.go +480 -0
  106. package/stdlib/slices/zsort_ordered.go +482 -0
  107. package/stdlib/sort/sort.go +391 -452
  108. package/stdlib/sort/zsort_func.go +480 -0
  109. package/stdlib/sort/zsort_iface.go +480 -0
  110. package/stdlib/strconv/float.go +1699 -0
  111. package/stdlib/strconv/isprint.go +752 -0
  112. package/stdlib/strconv/quote.go +235 -50
  113. package/stdlib/strconv/strconv.go +616 -0
  114. package/stdlib/strings/builder.go +95 -0
  115. package/stdlib/strings/reader.go +163 -0
  116. package/stdlib/strings/replacer.go +102 -0
  117. package/stdlib/strings/strings.go +807 -0
  118. package/stdlib/sync/sync.go +268 -0
  119. package/stdlib/testing/async_js.go +61 -0
  120. package/stdlib/testing/benchmark.go +297 -0
  121. package/stdlib/testing/testing.go +523 -0
  122. package/stdlib/time/duration.go +233 -0
  123. package/stdlib/time/format.go +745 -0
  124. package/stdlib/time/parse.go +790 -0
  125. package/stdlib/time/sleep_js.go +63 -0
  126. package/stdlib/time/time.go +834 -0
  127. package/stdlib/unicode/unicode.go +141 -3
  128. package/stdlib/unicode/utf8/utf8.go +464 -0
  129. package/src/backend/js/fmt-runtime.js +0 -573
  130. package/src/backend/js/stdlib/base64.js +0 -12
  131. package/src/backend/js/stdlib/binary.js +0 -102
  132. package/src/backend/js/stdlib/bits.js +0 -119
  133. package/src/backend/js/stdlib/builder.js +0 -98
  134. package/src/backend/js/stdlib/bytes.js +0 -368
  135. package/src/backend/js/stdlib/errors.js +0 -45
  136. package/src/backend/js/stdlib/fmt.js +0 -517
  137. package/src/backend/js/stdlib/gom.js +0 -155
  138. package/src/backend/js/stdlib/hex.js +0 -17
  139. package/src/backend/js/stdlib/html.js +0 -20
  140. package/src/backend/js/stdlib/io.js +0 -137
  141. package/src/backend/js/stdlib/json.js +0 -1167
  142. package/src/backend/js/stdlib/maps.js +0 -37
  143. package/src/backend/js/stdlib/math.js +0 -85
  144. package/src/backend/js/stdlib/os.js +0 -13
  145. package/src/backend/js/stdlib/path.js +0 -48
  146. package/src/backend/js/stdlib/rand.js +0 -32
  147. package/src/backend/js/stdlib/regexp.js +0 -54
  148. package/src/backend/js/stdlib/sha256.js +0 -12
  149. package/src/backend/js/stdlib/shared.js +0 -17
  150. package/src/backend/js/stdlib/simd.js +0 -34
  151. package/src/backend/js/stdlib/slices.js +0 -107
  152. package/src/backend/js/stdlib/sort.js +0 -30
  153. package/src/backend/js/stdlib/strconv.js +0 -79
  154. package/src/backend/js/stdlib/strings.js +0 -301
  155. package/src/backend/js/stdlib/sync.js +0 -13
  156. package/src/backend/js/stdlib/testing.js +0 -41
  157. package/src/backend/js/stdlib/time.js +0 -152
  158. package/src/backend/js/stdlib/unicode.js +0 -25
  159. package/src/backend/js/stdlib/utf8.js +0 -26
  160. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  161. package/src/backend/wasm/stdlib/core.js +0 -10278
  162. package/src/backend/wasm/stdlib/io.js +0 -3578
  163. package/src/backend/wasm/stdlib/packages.js +0 -2402
  164. package/src/backend/wasm/stdlib/pure.js +0 -720
  165. package/src/backend/wasm/stdlib/time.js +0 -2229
  166. package/src/typechecker/stdlib/core.js +0 -1079
  167. package/src/typechecker/stdlib/extended.js +0 -1210
  168. package/stdlib/bytes/iter.go +0 -192
  169. package/stdlib/bytes/search.go +0 -240
  170. package/stdlib/bytes/split.go +0 -218
  171. package/stdlib/errors/overlay.go +0 -12
  172. package/stdlib/maps/iter.go +0 -65
  173. package/stdlib/slices/extra.go +0 -73
  174. package/stdlib/slices/iter.go +0 -113
  175. package/stdlib/strings/extra.go +0 -35
  176. package/stdlib/strings/iter.go +0 -122
  177. package/stdlib/sync/extra.go +0 -105
  178. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -0,0 +1,480 @@
1
+ // Code generated by scripts/gen-pdq.js; DO NOT EDIT.
2
+
3
+ // Copyright 2022 The Go Authors. All rights reserved.
4
+ // Use of this source code is governed by a BSD-style
5
+ // license that can be found in the LICENSE file.
6
+
7
+ package sort
8
+
9
+ // insertionSort_func sorts data[a:b] using insertion sort.
10
+ func insertionSort_func(data lessSwap, a, b int) {
11
+ for i := a + 1; i < b; i++ {
12
+ for j := i; j > a && data.Less(j, j-1); j-- {
13
+ data.Swap(j, j-1)
14
+ }
15
+ }
16
+ }
17
+
18
+ // siftDown_func implements the heap property on data[lo:hi].
19
+ // first is an offset into the array where the root of the heap lies.
20
+ func siftDown_func(data lessSwap, lo, hi, first int) {
21
+ root := lo
22
+ for {
23
+ child := 2*root + 1
24
+ if child >= hi {
25
+ break
26
+ }
27
+ if child+1 < hi && data.Less(first+child, first+child+1) {
28
+ child++
29
+ }
30
+ if !data.Less(first+root, first+child) {
31
+ return
32
+ }
33
+ data.Swap(first+root, first+child)
34
+ root = child
35
+ }
36
+ }
37
+
38
+ func heapSort_func(data lessSwap, a, b int) {
39
+ first := a
40
+ lo := 0
41
+ hi := b - a
42
+
43
+ // Build heap with greatest element at top.
44
+ for i := (hi - 1) / 2; i >= 0; i-- {
45
+ siftDown_func(data, i, hi, first)
46
+ }
47
+
48
+ // Pop elements, largest first, into end of data.
49
+ for i := hi - 1; i >= 0; i-- {
50
+ data.Swap(first, first+i)
51
+ siftDown_func(data, lo, i, first)
52
+ }
53
+ }
54
+
55
+ // pdqsort_func sorts data[a:b].
56
+ // The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort.
57
+ // pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf
58
+ // C++ implementation: https://github.com/orlp/pdqsort
59
+ // Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/
60
+ // limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort.
61
+ func pdqsort_func(data lessSwap, a, b, limit int) {
62
+ const maxInsertion = 12
63
+
64
+ var (
65
+ wasBalanced = true // whether the last partitioning was reasonably balanced
66
+ wasPartitioned = true // whether the slice was already partitioned
67
+ )
68
+
69
+ for {
70
+ length := b - a
71
+
72
+ if length <= maxInsertion {
73
+ insertionSort_func(data, a, b)
74
+ return
75
+ }
76
+
77
+ // Fall back to heapsort if too many bad choices were made.
78
+ if limit == 0 {
79
+ heapSort_func(data, a, b)
80
+ return
81
+ }
82
+
83
+ // If the last partitioning was imbalanced, we need to breaking patterns.
84
+ if !wasBalanced {
85
+ breakPatterns_func(data, a, b)
86
+ limit--
87
+ }
88
+
89
+ pivot, hint := choosePivot_func(data, a, b)
90
+ if hint == decreasingHint {
91
+ reverseRange_func(data, a, b)
92
+ // The chosen pivot was pivot-a elements after the start of the array.
93
+ // After reversing it is pivot-a elements before the end of the array.
94
+ // The idea came from Rust's implementation.
95
+ pivot = (b - 1) - (pivot - a)
96
+ hint = increasingHint
97
+ }
98
+
99
+ // The slice is likely already sorted.
100
+ if wasBalanced && wasPartitioned && hint == increasingHint {
101
+ if partialInsertionSort_func(data, a, b) {
102
+ return
103
+ }
104
+ }
105
+
106
+ // Probably the slice contains many duplicate elements, partition the slice into
107
+ // elements equal to and elements greater than the pivot.
108
+ if a > 0 && !data.Less(a-1, pivot) {
109
+ mid := partitionEqual_func(data, a, b, pivot)
110
+ a = mid
111
+ continue
112
+ }
113
+
114
+ mid, alreadyPartitioned := partition_func(data, a, b, pivot)
115
+ wasPartitioned = alreadyPartitioned
116
+
117
+ leftLen, rightLen := mid-a, b-mid
118
+ balanceThreshold := length / 8
119
+ if leftLen < rightLen {
120
+ wasBalanced = leftLen >= balanceThreshold
121
+ pdqsort_func(data, a, mid, limit)
122
+ a = mid + 1
123
+ } else {
124
+ wasBalanced = rightLen >= balanceThreshold
125
+ pdqsort_func(data, mid+1, b, limit)
126
+ b = mid
127
+ }
128
+ }
129
+ }
130
+
131
+ // partition_func does one quicksort partition.
132
+ // Let p = data[pivot]
133
+ // Moves elements in data[a:b] around, so that data[i]<p and data[j]>=p for i<newpivot and j>newpivot.
134
+ // On return, data[newpivot] = p
135
+ func partition_func(data lessSwap, a, b, pivot int) (newpivot int, alreadyPartitioned bool) {
136
+ data.Swap(a, pivot)
137
+ i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
138
+
139
+ for i <= j && data.Less(i, a) {
140
+ i++
141
+ }
142
+ for i <= j && !data.Less(j, a) {
143
+ j--
144
+ }
145
+ if i > j {
146
+ data.Swap(j, a)
147
+ return j, true
148
+ }
149
+ data.Swap(i, j)
150
+ i++
151
+ j--
152
+
153
+ for {
154
+ for i <= j && data.Less(i, a) {
155
+ i++
156
+ }
157
+ for i <= j && !data.Less(j, a) {
158
+ j--
159
+ }
160
+ if i > j {
161
+ break
162
+ }
163
+ data.Swap(i, j)
164
+ i++
165
+ j--
166
+ }
167
+ data.Swap(j, a)
168
+ return j, false
169
+ }
170
+
171
+ // partitionEqual_func partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot].
172
+ // It assumed that data[a:b] does not contain elements smaller than the data[pivot].
173
+ func partitionEqual_func(data lessSwap, a, b, pivot int) (newpivot int) {
174
+ data.Swap(a, pivot)
175
+ i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned
176
+
177
+ for {
178
+ for i <= j && !data.Less(a, i) {
179
+ i++
180
+ }
181
+ for i <= j && data.Less(a, j) {
182
+ j--
183
+ }
184
+ if i > j {
185
+ break
186
+ }
187
+ data.Swap(i, j)
188
+ i++
189
+ j--
190
+ }
191
+ return i
192
+ }
193
+
194
+ // partialInsertionSort_func partially sorts a slice, returns true if the slice is sorted at the end.
195
+ func partialInsertionSort_func(data lessSwap, a, b int) bool {
196
+ const (
197
+ maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted
198
+ shortestShifting = 50 // don't shift any elements on short arrays
199
+ )
200
+ i := a + 1
201
+ for j := 0; j < maxSteps; j++ {
202
+ for i < b && !data.Less(i, i-1) {
203
+ i++
204
+ }
205
+
206
+ if i == b {
207
+ return true
208
+ }
209
+
210
+ if b-a < shortestShifting {
211
+ return false
212
+ }
213
+
214
+ data.Swap(i, i-1)
215
+
216
+ // Shift the smaller one to the left.
217
+ if i-a >= 2 {
218
+ for j := i - 1; j >= 1; j-- {
219
+ if !data.Less(j, j-1) {
220
+ break
221
+ }
222
+ data.Swap(j, j-1)
223
+ }
224
+ }
225
+ // Shift the greater one to the right.
226
+ if b-i >= 2 {
227
+ for j := i + 1; j < b; j++ {
228
+ if !data.Less(j, j-1) {
229
+ break
230
+ }
231
+ data.Swap(j, j-1)
232
+ }
233
+ }
234
+ }
235
+ return false
236
+ }
237
+
238
+ // breakPatterns_func scatters some elements around in an attempt to break some patterns
239
+ // that might cause imbalanced partitions in quicksort.
240
+ func breakPatterns_func(data lessSwap, a, b int) {
241
+ length := b - a
242
+ if length >= 8 {
243
+ random := xorshift(length)
244
+ modulus := nextPowerOfTwo(length)
245
+
246
+ for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ {
247
+ // Masked as a uint64 first: Go's uint(random.Next()) would round a value above 2^53 on JS.
248
+ other := int(random.Next() & uint64(modulus-1))
249
+ if other >= length {
250
+ other -= length
251
+ }
252
+ data.Swap(idx, a+other)
253
+ }
254
+ }
255
+ }
256
+
257
+ // choosePivot_func chooses a pivot in data[a:b].
258
+ //
259
+ // [0,8): chooses a static pivot.
260
+ // [8,shortestNinther): uses the simple median-of-three method.
261
+ // [shortestNinther,∞): uses the Tukey ninther method.
262
+ func choosePivot_func(data lessSwap, a, b int) (pivot int, hint sortedHint) {
263
+ const (
264
+ shortestNinther = 50
265
+ maxSwaps = 4 * 3
266
+ )
267
+
268
+ l := b - a
269
+
270
+ var (
271
+ swaps int
272
+ i = a + l/4*1
273
+ j = a + l/4*2
274
+ k = a + l/4*3
275
+ )
276
+
277
+ if l >= 8 {
278
+ if l >= shortestNinther {
279
+ // Tukey ninther method, the idea came from Rust's implementation.
280
+ i = medianAdjacent_func(data, i, &swaps)
281
+ j = medianAdjacent_func(data, j, &swaps)
282
+ k = medianAdjacent_func(data, k, &swaps)
283
+ }
284
+ // Find the median among i, j, k and stores it into j.
285
+ j = median_func(data, i, j, k, &swaps)
286
+ }
287
+
288
+ switch swaps {
289
+ case 0:
290
+ return j, increasingHint
291
+ case maxSwaps:
292
+ return j, decreasingHint
293
+ default:
294
+ return j, unknownHint
295
+ }
296
+ }
297
+
298
+ // order2_func returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a.
299
+ func order2_func(data lessSwap, a, b int, swaps *int) (int, int) {
300
+ if data.Less(b, a) {
301
+ *swaps++
302
+ return b, a
303
+ }
304
+ return a, b
305
+ }
306
+
307
+ // median_func returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c.
308
+ func median_func(data lessSwap, a, b, c int, swaps *int) int {
309
+ a, b = order2_func(data, a, b, swaps)
310
+ b, c = order2_func(data, b, c, swaps)
311
+ a, b = order2_func(data, a, b, swaps)
312
+ return b
313
+ }
314
+
315
+ // medianAdjacent_func finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a.
316
+ func medianAdjacent_func(data lessSwap, a int, swaps *int) int {
317
+ return median_func(data, a-1, a, a+1, swaps)
318
+ }
319
+
320
+ func reverseRange_func(data lessSwap, a, b int) {
321
+ i := a
322
+ j := b - 1
323
+ for i < j {
324
+ data.Swap(i, j)
325
+ i++
326
+ j--
327
+ }
328
+ }
329
+
330
+ func swapRange_func(data lessSwap, a, b, n int) {
331
+ for i := 0; i < n; i++ {
332
+ data.Swap(a+i, b+i)
333
+ }
334
+ }
335
+
336
+ func stable_func(data lessSwap, n int) {
337
+ blockSize := 20 // must be > 0
338
+ a, b := 0, blockSize
339
+ for b <= n {
340
+ insertionSort_func(data, a, b)
341
+ a = b
342
+ b += blockSize
343
+ }
344
+ insertionSort_func(data, a, n)
345
+
346
+ for blockSize < n {
347
+ a, b = 0, 2*blockSize
348
+ for b <= n {
349
+ symMerge_func(data, a, a+blockSize, b)
350
+ a = b
351
+ b += 2 * blockSize
352
+ }
353
+ if m := a + blockSize; m < n {
354
+ symMerge_func(data, a, m, n)
355
+ }
356
+ blockSize *= 2
357
+ }
358
+ }
359
+
360
+ // symMerge_func merges the two sorted subsequences data[a:m] and data[m:b] using
361
+ // the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
362
+ // Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
363
+ // Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
364
+ // Computer Science, pages 714-723. Springer, 2004.
365
+ //
366
+ // Let M = m-a and N = b-n. Wolog M < N.
367
+ // The recursion depth is bound by ceil(log(N+M)).
368
+ // The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
369
+ // The algorithm needs O((M+N)*log(M)) calls to data.Swap.
370
+ //
371
+ // The paper gives O((M+N)*log(M)) as the number of assignments assuming a
372
+ // rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation
373
+ // in the paper carries through for Swap operations, especially as the block
374
+ // swapping rotate uses only O(M+N) Swaps.
375
+ //
376
+ // symMerge assumes non-degenerate arguments: a < m && m < b.
377
+ // Having the caller check this condition eliminates many leaf recursion calls,
378
+ // which improves performance.
379
+ func symMerge_func(data lessSwap, a, m, b int) {
380
+ // Avoid unnecessary recursions of symMerge
381
+ // by direct insertion of data[a] into data[m:b]
382
+ // if data[a:m] only contains one element.
383
+ if m-a == 1 {
384
+ // Use binary search to find the lowest index i
385
+ // such that data[i] >= data[a] for m <= i < b.
386
+ // Exit the search loop with i == b in case no such index exists.
387
+ i := m
388
+ j := b
389
+ for i < j {
390
+ h := int(uint(i+j) >> 1)
391
+ if data.Less(h, a) {
392
+ i = h + 1
393
+ } else {
394
+ j = h
395
+ }
396
+ }
397
+ // Swap values until data[a] reaches the position before i.
398
+ for k := a; k < i-1; k++ {
399
+ data.Swap(k, k+1)
400
+ }
401
+ return
402
+ }
403
+
404
+ // Avoid unnecessary recursions of symMerge
405
+ // by direct insertion of data[m] into data[a:m]
406
+ // if data[m:b] only contains one element.
407
+ if b-m == 1 {
408
+ // Use binary search to find the lowest index i
409
+ // such that data[i] > data[m] for a <= i < m.
410
+ // Exit the search loop with i == m in case no such index exists.
411
+ i := a
412
+ j := m
413
+ for i < j {
414
+ h := int(uint(i+j) >> 1)
415
+ if !data.Less(m, h) {
416
+ i = h + 1
417
+ } else {
418
+ j = h
419
+ }
420
+ }
421
+ // Swap values until data[m] reaches the position i.
422
+ for k := m; k > i; k-- {
423
+ data.Swap(k, k-1)
424
+ }
425
+ return
426
+ }
427
+
428
+ mid := int(uint(a+b) >> 1)
429
+ n := mid + m
430
+ var start, r int
431
+ if m > mid {
432
+ start = n - b
433
+ r = mid
434
+ } else {
435
+ start = a
436
+ r = m
437
+ }
438
+ p := n - 1
439
+
440
+ for start < r {
441
+ c := int(uint(start+r) >> 1)
442
+ if !data.Less(p-c, c) {
443
+ start = c + 1
444
+ } else {
445
+ r = c
446
+ }
447
+ }
448
+
449
+ end := n - start
450
+ if start < m && m < end {
451
+ rotate_func(data, start, m, end)
452
+ }
453
+ if a < start && start < mid {
454
+ symMerge_func(data, a, start, mid)
455
+ }
456
+ if mid < end && end < b {
457
+ symMerge_func(data, mid, end, b)
458
+ }
459
+ }
460
+
461
+ // rotate_func rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data:
462
+ // Data of the form 'x u v y' is changed to 'x v u y'.
463
+ // rotate performs at most b-a many calls to data.Swap,
464
+ // and it assumes non-degenerate arguments: a < m && m < b.
465
+ func rotate_func(data lessSwap, a, m, b int) {
466
+ i := m - a
467
+ j := b - m
468
+
469
+ for i != j {
470
+ if i > j {
471
+ swapRange_func(data, m-i, m, j)
472
+ i -= j
473
+ } else {
474
+ swapRange_func(data, m-i, m+j-i, i)
475
+ j -= i
476
+ }
477
+ }
478
+ // i == j
479
+ swapRange_func(data, m-i, m, i)
480
+ }