gofront 1.7.0 → 1.8.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 (128) hide show
  1. package/README.md +13 -13
  2. package/package.json +8 -37
  3. package/src/backend/js/expressions.js +1341 -148
  4. package/src/backend/js/fmt-runtime.js +573 -0
  5. package/src/backend/js/index.js +375 -57
  6. package/src/backend/js/runtime.js +1460 -133
  7. package/src/backend/js/statements.js +900 -86
  8. package/src/backend/js/stdlib/bits.js +87 -14
  9. package/src/backend/js/stdlib/builder.js +41 -6
  10. package/src/backend/js/stdlib/bytes.js +253 -7
  11. package/src/backend/js/stdlib/errors.js +2 -1
  12. package/src/backend/js/stdlib/fmt.js +349 -10
  13. package/src/backend/js/stdlib/index.js +8 -3
  14. package/src/backend/js/stdlib/json.js +247 -52
  15. package/src/backend/js/stdlib/maps.js +0 -8
  16. package/src/backend/js/stdlib/math.js +17 -1
  17. package/src/backend/js/stdlib/simd.js +10 -0
  18. package/src/backend/js/stdlib/slices.js +36 -6
  19. package/src/backend/js/stdlib/strconv.js +10 -5
  20. package/src/backend/js/stdlib/strings.js +83 -4
  21. package/src/backend/js/stdlib/testing.js +7 -0
  22. package/src/backend/js/stdlib/time.js +79 -55
  23. package/src/backend/js/stdlib/unicode.js +1 -1
  24. package/src/backend/js/stdlib/utf8.js +1 -1
  25. package/src/backend/js/templ.js +38 -76
  26. package/src/backend/js/type-info.js +272 -0
  27. package/src/backend/shared/fmt-types.js +188 -0
  28. package/src/backend/wasm/boundary.js +436 -80
  29. package/src/backend/wasm/emit-builtins.js +303 -13
  30. package/src/backend/wasm/emit-exprs.js +1397 -203
  31. package/src/backend/wasm/emit-maps.js +61 -13
  32. package/src/backend/wasm/emit-stmts.js +1359 -164
  33. package/src/backend/wasm/emit.js +512 -77
  34. package/src/backend/wasm/encode.js +43 -13
  35. package/src/backend/wasm/globals.js +452 -0
  36. package/src/backend/wasm/index.js +194 -2489
  37. package/src/backend/wasm/method-expr.js +381 -0
  38. package/src/backend/wasm/module-emitter.js +2240 -0
  39. package/src/backend/wasm/monomorph.js +62 -4
  40. package/src/backend/wasm/prescan.js +397 -0
  41. package/src/backend/wasm/stdlib/bytes.js +1804 -127
  42. package/src/backend/wasm/stdlib/core.js +1574 -199
  43. package/src/backend/wasm/stdlib/index.js +0 -5
  44. package/src/backend/wasm/stdlib/io.js +1567 -150
  45. package/src/backend/wasm/stdlib/packages.js +2 -0
  46. package/src/backend/wasm/stdlib/simd.js +293 -28
  47. package/src/backend/wasm/stdlib/time.js +1041 -12
  48. package/src/backend/wasm/types.js +200 -15
  49. package/src/backend/wasm/variadic.js +93 -0
  50. package/src/backend/wasm/wat.js +47 -20
  51. package/src/{cli-core.js → cli/cli-core.js} +236 -10
  52. package/src/{test-runner.js → cli/test-runner.js} +332 -39
  53. package/src/{vendor.js → cli/vendor.js} +3 -4
  54. package/src/compiler.js +107 -269
  55. package/src/index.js +15 -169
  56. package/src/{lexer.js → lexer/lexer.js} +102 -55
  57. package/src/{tokens.js → lexer/tokens.js} +1 -0
  58. package/src/link/sourcemap.js +97 -0
  59. package/src/link/stdlib.js +515 -0
  60. package/src/link/wasm.js +294 -0
  61. package/src/lower/bounds.js +394 -0
  62. package/src/lower/boxing.js +1 -1
  63. package/src/lower/captures.js +176 -32
  64. package/src/lower/index.js +26 -18
  65. package/src/lower/json-codecs.js +1398 -0
  66. package/src/lower/ownership.js +22 -1
  67. package/src/lower/range.js +86 -1
  68. package/src/lower/reachability.js +132 -0
  69. package/src/parser/declarations.js +58 -13
  70. package/src/parser/expressions.js +29 -7
  71. package/src/parser/index.js +2 -1
  72. package/src/parser/statements.js +37 -22
  73. package/src/{templ-parser.js → parser/templ.js} +138 -15
  74. package/src/parser/types.js +69 -9
  75. package/src/resolver.js +22 -1
  76. package/src/typechecker/assignability.js +176 -17
  77. package/src/typechecker/const-fold.js +356 -0
  78. package/src/typechecker/constants.js +256 -0
  79. package/src/typechecker/expressions.js +931 -122
  80. package/src/typechecker/index.js +459 -67
  81. package/src/typechecker/init-order.js +330 -0
  82. package/src/typechecker/resolve.js +451 -56
  83. package/src/typechecker/statements.js +90 -9
  84. package/src/typechecker/stdlib/core.js +333 -55
  85. package/src/typechecker/stdlib/excluded.js +898 -0
  86. package/src/typechecker/stdlib/extended.js +322 -26
  87. package/src/typechecker/{stdlib.js → stdlib/index.js} +5 -5
  88. package/src/typechecker/stdlib/simd.js +65 -15
  89. package/src/typechecker/termination.js +1 -1
  90. package/src/typechecker/types.js +149 -25
  91. package/stdlib/bytes/iter.go +192 -0
  92. package/stdlib/bytes/search.go +240 -0
  93. package/stdlib/bytes/split.go +218 -0
  94. package/stdlib/cmp/cmp.go +65 -0
  95. package/stdlib/encoding/json/errors.go +31 -0
  96. package/stdlib/encoding/json/indent.go +71 -0
  97. package/stdlib/encoding/json/number.go +12 -0
  98. package/stdlib/encoding/json/stream.go +173 -0
  99. package/stdlib/errors/overlay.go +12 -0
  100. package/stdlib/hash/hash.go +53 -0
  101. package/stdlib/internal/jsonrt/dec.go +738 -0
  102. package/stdlib/internal/jsonrt/enc.go +366 -0
  103. package/stdlib/internal/jsonrt/indent.go +135 -0
  104. package/stdlib/internal/jsonrt/number.go +27 -0
  105. package/stdlib/internal/jsonrt/reader.go +73 -0
  106. package/stdlib/internal/jsonrt/scanner.go +649 -0
  107. package/stdlib/io/io.go +346 -0
  108. package/stdlib/iter/iter.go +18 -0
  109. package/stdlib/maps/iter.go +65 -0
  110. package/stdlib/math/extra.go +270 -0
  111. package/stdlib/slices/extra.go +73 -0
  112. package/stdlib/slices/iter.go +113 -0
  113. package/stdlib/sort/sort.go +561 -0
  114. package/stdlib/strconv/quote.go +341 -0
  115. package/stdlib/strings/extra.go +35 -0
  116. package/stdlib/strings/iter.go +122 -0
  117. package/stdlib/sync/extra.go +105 -0
  118. package/stdlib/unicode/unicode.go +112 -0
  119. package/stdlib/unicode/utf8/bytes.go +239 -0
  120. package/src/backend/wasm/const-fold.js +0 -205
  121. package/src/backend/wasm/emit-stdlib.js +0 -13
  122. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  123. /package/src/{colors.js → cli/colors.js} +0 -0
  124. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  125. /package/src/{minifier.js → cli/minifier.js} +0 -0
  126. /package/src/{project-config.js → cli/project-config.js} +0 -0
  127. /package/src/{pwa.js → cli/pwa.js} +0 -0
  128. /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
@@ -0,0 +1,561 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Overlay on the emitter-backed sort package: Interface, Sort (pdqsort),
6
+ // Stable, Reverse, IsSorted, Search*, and *Slice types.
7
+ package sort
8
+
9
+ // An implementation of Interface can be sorted by the routines in this package.
10
+ type Interface interface {
11
+ Len() int
12
+ Less(i, j int) bool
13
+ Swap(i, j int)
14
+ }
15
+
16
+ func bitsLen(n uint) int {
17
+ var l int
18
+ for n > 0 {
19
+ l++
20
+ n >>= 1
21
+ }
22
+ return l
23
+ }
24
+
25
+ // Sort sorts data in ascending order as determined by the Less method.
26
+ // It uses pattern-defeating quicksort (pdqsort) so equal-element order matches Go.
27
+ func Sort(data Interface) {
28
+ n := data.Len()
29
+ if n <= 1 {
30
+ return
31
+ }
32
+ limit := bitsLen(uint(n))
33
+ pdqsort(data, 0, n, limit)
34
+ }
35
+
36
+ // Stable sorts data in ascending order as determined by the Less method,
37
+ // while keeping the original order of equal elements.
38
+ func Stable(data Interface) {
39
+ stable(data, data.Len())
40
+ }
41
+
42
+ // IsSorted reports whether data is sorted.
43
+ func IsSorted(data Interface) bool {
44
+ n := data.Len()
45
+ for i := n - 1; i > 0; i-- {
46
+ if data.Less(i, i-1) {
47
+ return false
48
+ }
49
+ }
50
+ return true
51
+ }
52
+
53
+ type reverse struct {
54
+ data Interface
55
+ }
56
+
57
+ func (r *reverse) Len() int {
58
+ return r.data.Len()
59
+ }
60
+
61
+ func (r *reverse) Less(i, j int) bool {
62
+ return r.data.Less(j, i)
63
+ }
64
+
65
+ func (r *reverse) Swap(i, j int) {
66
+ r.data.Swap(i, j)
67
+ }
68
+
69
+ // Reverse returns the reverse order for data.
70
+ func Reverse(data Interface) Interface {
71
+ return &reverse{data: data}
72
+ }
73
+
74
+ type sortedHint int
75
+
76
+ const (
77
+ unknownHint sortedHint = iota
78
+ increasingHint
79
+ decreasingHint
80
+ )
81
+
82
+ const (
83
+ maxInsertion = 12
84
+ maxSteps = 5
85
+ shortestShifting = 50
86
+ shortestNinther = 50
87
+ maxSwaps = 4 * 3
88
+ )
89
+
90
+ type xorshift uint64
91
+
92
+ func (r *xorshift) Next() uint64 {
93
+ *r ^= *r << 13
94
+ *r ^= *r >> 7
95
+ *r ^= *r << 17
96
+ return uint64(*r)
97
+ }
98
+
99
+ func nextPowerOfTwo(length int) uint {
100
+ shift := uint(bitsLen(uint(length)))
101
+ return uint(1 << shift)
102
+ }
103
+
104
+ func insertionSort(data Interface, a, b int) {
105
+ for i := a + 1; i < b; i++ {
106
+ for j := i; j > a && data.Less(j, j-1); j-- {
107
+ data.Swap(j, j-1)
108
+ }
109
+ }
110
+ }
111
+
112
+ func siftDown(data Interface, lo, hi, first int) {
113
+ root := lo
114
+ for {
115
+ child := 2*root + 1
116
+ if child >= hi {
117
+ break
118
+ }
119
+ if child+1 < hi && data.Less(first+child, first+child+1) {
120
+ child++
121
+ }
122
+ if !data.Less(first+root, first+child) {
123
+ return
124
+ }
125
+ data.Swap(first+root, first+child)
126
+ root = child
127
+ }
128
+ }
129
+
130
+ func heapSort(data Interface, a, b int) {
131
+ first := a
132
+ lo := 0
133
+ hi := b - a
134
+
135
+ for i := (hi - 1) / 2; i >= 0; i-- {
136
+ siftDown(data, i, hi, first)
137
+ }
138
+
139
+ for i := hi - 1; i >= 0; i-- {
140
+ data.Swap(first, first+i)
141
+ siftDown(data, lo, i, first)
142
+ }
143
+ }
144
+
145
+ func pdqsort(data Interface, a, b, limit int) {
146
+ var (
147
+ wasBalanced = true
148
+ wasPartitioned = true
149
+ )
150
+
151
+ for {
152
+ length := b - a
153
+
154
+ if length <= maxInsertion {
155
+ insertionSort(data, a, b)
156
+ return
157
+ }
158
+
159
+ if limit == 0 {
160
+ heapSort(data, a, b)
161
+ return
162
+ }
163
+
164
+ if !wasBalanced {
165
+ breakPatterns(data, a, b)
166
+ limit--
167
+ }
168
+
169
+ pivot, hint := choosePivot(data, a, b)
170
+ if hint == decreasingHint {
171
+ reverseRange(data, a, b)
172
+ pivot = (b - 1) - (pivot - a)
173
+ hint = increasingHint
174
+ }
175
+
176
+ if wasBalanced && wasPartitioned && hint == increasingHint {
177
+ if partialInsertionSort(data, a, b) {
178
+ return
179
+ }
180
+ }
181
+
182
+ if a > 0 && !data.Less(a-1, pivot) {
183
+ mid := partitionEqual(data, a, b, pivot)
184
+ a = mid
185
+ continue
186
+ }
187
+
188
+ mid, alreadyPartitioned := partition(data, a, b, pivot)
189
+ wasPartitioned = alreadyPartitioned
190
+
191
+ leftLen, rightLen := mid-a, b-mid
192
+ balanceThreshold := length / 8
193
+ if leftLen < rightLen {
194
+ wasBalanced = leftLen >= balanceThreshold
195
+ pdqsort(data, a, mid, limit)
196
+ a = mid + 1
197
+ } else {
198
+ wasBalanced = rightLen >= balanceThreshold
199
+ pdqsort(data, mid+1, b, limit)
200
+ b = mid
201
+ }
202
+ }
203
+ }
204
+
205
+ func partition(data Interface, a, b, pivot int) (newpivot int, alreadyPartitioned bool) {
206
+ data.Swap(a, pivot)
207
+ i, j := a+1, b-1
208
+
209
+ for i <= j && data.Less(i, a) {
210
+ i++
211
+ }
212
+ for i <= j && !data.Less(j, a) {
213
+ j--
214
+ }
215
+ if i > j {
216
+ data.Swap(j, a)
217
+ return j, true
218
+ }
219
+ data.Swap(i, j)
220
+ i++
221
+ j--
222
+
223
+ for {
224
+ for i <= j && data.Less(i, a) {
225
+ i++
226
+ }
227
+ for i <= j && !data.Less(j, a) {
228
+ j--
229
+ }
230
+ if i > j {
231
+ break
232
+ }
233
+ data.Swap(i, j)
234
+ i++
235
+ j--
236
+ }
237
+ data.Swap(j, a)
238
+ return j, false
239
+ }
240
+
241
+ func partitionEqual(data Interface, a, b, pivot int) (newpivot int) {
242
+ data.Swap(a, pivot)
243
+ i, j := a+1, b-1
244
+
245
+ for {
246
+ for i <= j && !data.Less(a, i) {
247
+ i++
248
+ }
249
+ for i <= j && data.Less(a, j) {
250
+ j--
251
+ }
252
+ if i > j {
253
+ break
254
+ }
255
+ data.Swap(i, j)
256
+ i++
257
+ j--
258
+ }
259
+ return i
260
+ }
261
+
262
+ func partialInsertionSort(data Interface, a, b int) bool {
263
+ i := a + 1
264
+ for j := 0; j < maxSteps; j++ {
265
+ for i < b && !data.Less(i, i-1) {
266
+ i++
267
+ }
268
+
269
+ if i == b {
270
+ return true
271
+ }
272
+
273
+ if b-a < shortestShifting {
274
+ return false
275
+ }
276
+
277
+ data.Swap(i, i-1)
278
+
279
+ if i-a >= 2 {
280
+ for j := i - 1; j >= 1; j-- {
281
+ if !data.Less(j, j-1) {
282
+ break
283
+ }
284
+ data.Swap(j, j-1)
285
+ }
286
+ }
287
+ if b-i >= 2 {
288
+ for j := i + 1; j < b; j++ {
289
+ if !data.Less(j, j-1) {
290
+ break
291
+ }
292
+ data.Swap(j, j-1)
293
+ }
294
+ }
295
+ }
296
+ return false
297
+ }
298
+
299
+ func breakPatterns(data Interface, a, b int) {
300
+ length := b - a
301
+ if length >= 8 {
302
+ random := xorshift(length)
303
+ modulus := nextPowerOfTwo(length)
304
+
305
+ for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ {
306
+ other := int(uint(random.Next()) & (modulus - 1))
307
+ if other >= length {
308
+ other -= length
309
+ }
310
+ data.Swap(idx, a+other)
311
+ }
312
+ }
313
+ }
314
+
315
+ func choosePivot(data Interface, a, b int) (pivot int, hint sortedHint) {
316
+ l := b - a
317
+
318
+ var (
319
+ swaps int
320
+ i = a + l/4*1
321
+ j = a + l/4*2
322
+ k = a + l/4*3
323
+ )
324
+
325
+ if l >= 8 {
326
+ if l >= shortestNinther {
327
+ i = medianAdjacent(data, i, &swaps)
328
+ j = medianAdjacent(data, j, &swaps)
329
+ k = medianAdjacent(data, k, &swaps)
330
+ }
331
+ j = median(data, i, j, k, &swaps)
332
+ }
333
+
334
+ switch swaps {
335
+ case 0:
336
+ return j, increasingHint
337
+ case maxSwaps:
338
+ return j, decreasingHint
339
+ default:
340
+ return j, unknownHint
341
+ }
342
+ }
343
+
344
+ func order2(data Interface, a, b int, swaps *int) (int, int) {
345
+ if data.Less(b, a) {
346
+ *swaps++
347
+ return b, a
348
+ }
349
+ return a, b
350
+ }
351
+
352
+ func median(data Interface, a, b, c int, swaps *int) int {
353
+ a, b = order2(data, a, b, swaps)
354
+ b, c = order2(data, b, c, swaps)
355
+ a, b = order2(data, a, b, swaps)
356
+ return b
357
+ }
358
+
359
+ func medianAdjacent(data Interface, a int, swaps *int) int {
360
+ return median(data, a-1, a, a+1, swaps)
361
+ }
362
+
363
+ func reverseRange(data Interface, a, b int) {
364
+ i := a
365
+ j := b - 1
366
+ for i < j {
367
+ data.Swap(i, j)
368
+ i++
369
+ j--
370
+ }
371
+ }
372
+
373
+ func swapRange(data Interface, a, b, n int) {
374
+ for i := 0; i < n; i++ {
375
+ data.Swap(a+i, b+i)
376
+ }
377
+ }
378
+
379
+ func stable(data Interface, n int) {
380
+ blockSize := 20
381
+ a, b := 0, blockSize
382
+ for b <= n {
383
+ insertionSort(data, a, b)
384
+ a = b
385
+ b += blockSize
386
+ }
387
+ insertionSort(data, a, n)
388
+
389
+ for blockSize < n {
390
+ a, b = 0, 2*blockSize
391
+ for b <= n {
392
+ symMerge(data, a, a+blockSize, b)
393
+ a = b
394
+ b += 2 * blockSize
395
+ }
396
+ if m := a + blockSize; m < n {
397
+ symMerge(data, a, m, n)
398
+ }
399
+ blockSize *= 2
400
+ }
401
+ }
402
+
403
+ func symMergeBase(data Interface, a, m, b int) bool {
404
+ if m-a == 1 {
405
+ i := m
406
+ j := b
407
+ for i < j {
408
+ h := int(uint(i+j) >> 1)
409
+ if data.Less(h, a) {
410
+ i = h + 1
411
+ } else {
412
+ j = h
413
+ }
414
+ }
415
+ for k := a; k < i-1; k++ {
416
+ data.Swap(k, k+1)
417
+ }
418
+ return true
419
+ }
420
+
421
+ if b-m == 1 {
422
+ i := a
423
+ j := m
424
+ for i < j {
425
+ h := int(uint(i+j) >> 1)
426
+ if !data.Less(m, h) {
427
+ i = h + 1
428
+ } else {
429
+ j = h
430
+ }
431
+ }
432
+ for k := m; k > i; k-- {
433
+ data.Swap(k, k-1)
434
+ }
435
+ return true
436
+ }
437
+ return false
438
+ }
439
+
440
+ func symMerge(data Interface, a, m, b int) {
441
+ if symMergeBase(data, a, m, b) {
442
+ return
443
+ }
444
+
445
+ mid := int(uint(a+b) >> 1)
446
+ n := mid + m
447
+ var start, r int
448
+ if m > mid {
449
+ start = n - b
450
+ r = mid
451
+ } else {
452
+ start = a
453
+ r = m
454
+ }
455
+ p := n - 1
456
+
457
+ for start < r {
458
+ c := int(uint(start+r) >> 1)
459
+ if !data.Less(p-c, c) {
460
+ start = c + 1
461
+ } else {
462
+ r = c
463
+ }
464
+ }
465
+
466
+ end := n - start
467
+ if start < m && m < end {
468
+ rotate(data, start, m, end)
469
+ }
470
+ if a < start && start < mid {
471
+ symMerge(data, a, start, mid)
472
+ }
473
+ if mid < end && end < b {
474
+ symMerge(data, mid, end, b)
475
+ }
476
+ }
477
+
478
+ func rotate(data Interface, a, m, b int) {
479
+ i := m - a
480
+ j := b - m
481
+
482
+ for i != j {
483
+ if i > j {
484
+ swapRange(data, m-i, m, j)
485
+ i -= j
486
+ } else {
487
+ swapRange(data, m-i, m+j-i, i)
488
+ j -= i
489
+ }
490
+ }
491
+ swapRange(data, m-i, m, i)
492
+ }
493
+
494
+ // Find uses binary search to find and return the smallest index i in [0, n)
495
+ // at which cmp(i) <= 0. If there is no such index i, Find returns i = n.
496
+ // The found result is true if i < n and cmp(i) == 0.
497
+ // Find calls cmp(i) only for i in the range [0, n).
498
+ func Find(n int, cmp func(int) int) (i int, found bool) {
499
+ i, j := 0, n
500
+ for i < j {
501
+ h := int(uint(i+j) >> 1)
502
+ if cmp(h) > 0 {
503
+ i = h + 1
504
+ } else {
505
+ j = h
506
+ }
507
+ }
508
+ return i, i < n && cmp(i) == 0
509
+ }
510
+
511
+ // SearchInts searches for x in a sorted slice of ints and returns the index
512
+ // as specified by Search.
513
+ func SearchInts(a []int, x int) int {
514
+ return Search(len(a), func(i int) bool { return a[i] >= x })
515
+ }
516
+
517
+ // SearchFloat64s searches for x in a sorted slice of float64s and returns the index
518
+ // as specified by Search.
519
+ func SearchFloat64s(a []float64, x float64) int {
520
+ return Search(len(a), func(i int) bool { return a[i] >= x })
521
+ }
522
+
523
+ // SearchStrings searches for x in a sorted slice of strings and returns the index
524
+ // as specified by Search.
525
+ func SearchStrings(a []string, x string) int {
526
+ return Search(len(a), func(i int) bool { return a[i] >= x })
527
+ }
528
+
529
+ func isNaN(f float64) bool {
530
+ return f != f
531
+ }
532
+
533
+ // IntSlice attaches the methods of Interface to []int, sorting in increasing order.
534
+ type IntSlice []int
535
+
536
+ func (x IntSlice) Len() int { return len(x) }
537
+ func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
538
+ func (x IntSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
539
+ func (x IntSlice) Sort() { Sort(x) }
540
+ func (x IntSlice) Search(target int) int { return SearchInts(x, target) }
541
+
542
+ // StringSlice attaches the methods of Interface to []string, sorting in increasing order.
543
+ type StringSlice []string
544
+
545
+ func (x StringSlice) Len() int { return len(x) }
546
+ func (x StringSlice) Less(i, j int) bool { return x[i] < x[j] }
547
+ func (x StringSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
548
+ func (x StringSlice) Sort() { Sort(x) }
549
+ func (x StringSlice) Search(target string) int { return SearchStrings(x, target) }
550
+
551
+ // Float64Slice attaches the methods of Interface to []float64, sorting in increasing order,
552
+ // with not-a-number (NaN) values ordered before other values.
553
+ type Float64Slice []float64
554
+
555
+ func (x Float64Slice) Len() int { return len(x) }
556
+ func (x Float64Slice) Less(i, j int) bool {
557
+ return x[i] < x[j] || (isNaN(x[i]) && !isNaN(x[j]))
558
+ }
559
+ func (x Float64Slice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
560
+ func (x Float64Slice) Sort() { Sort(x) }
561
+ func (x Float64Slice) Search(target float64) int { return SearchFloat64s(x, target) }