| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- /*
- * SPDX-FileCopyrightText: © Hypermode Inc. <hello@hypermode.com>
- * SPDX-License-Identifier: Apache-2.0
- */
- package simd
- import (
- "fmt"
- "runtime"
- "sort"
- "sync"
- )
- // Search finds the key using the naive way
- func Naive(xs []uint64, k uint64) int16 {
- var i int
- for i = 0; i < len(xs); i += 2 {
- x := xs[i]
- if x >= k {
- return int16(i / 2)
- }
- }
- return int16(i / 2)
- }
- func Clever(xs []uint64, k uint64) int16 {
- if len(xs) < 8 {
- return Naive(xs, k)
- }
- var twos, pk [4]uint64
- pk[0] = k
- pk[1] = k
- pk[2] = k
- pk[3] = k
- for i := 0; i < len(xs); i += 8 {
- twos[0] = xs[i]
- twos[1] = xs[i+2]
- twos[2] = xs[i+4]
- twos[3] = xs[i+6]
- if twos[0] >= pk[0] {
- return int16(i / 2)
- }
- if twos[1] >= pk[1] {
- return int16((i + 2) / 2)
- }
- if twos[2] >= pk[2] {
- return int16((i + 4) / 2)
- }
- if twos[3] >= pk[3] {
- return int16((i + 6) / 2)
- }
- }
- return int16(len(xs) / 2)
- }
- func Parallel(xs []uint64, k uint64) int16 {
- cpus := runtime.NumCPU()
- if cpus%2 != 0 {
- panic(fmt.Sprintf("odd number of CPUs %v", cpus))
- }
- sz := len(xs)/cpus + 1
- var wg sync.WaitGroup
- retChan := make(chan int16, cpus)
- for i := 0; i < len(xs); i += sz {
- end := i + sz
- if end >= len(xs) {
- end = len(xs)
- }
- chunk := xs[i:end]
- wg.Add(1)
- go func(hd int16, xs []uint64, k uint64, wg *sync.WaitGroup, ch chan int16) {
- for i := 0; i < len(xs); i += 2 {
- if xs[i] >= k {
- ch <- (int16(i) + hd) / 2
- break
- }
- }
- wg.Done()
- }(int16(i), chunk, k, &wg, retChan)
- }
- wg.Wait()
- close(retChan)
- var min int16 = (1 << 15) - 1
- for i := range retChan {
- if i < min {
- min = i
- }
- }
- if min == (1<<15)-1 {
- return int16(len(xs) / 2)
- }
- return min
- }
- func Binary(keys []uint64, key uint64) int16 {
- return int16(sort.Search(len(keys), func(i int) bool {
- if i*2 >= len(keys) {
- return true
- }
- return keys[i*2] >= key
- }))
- }
- //nolint:unused
- func cmp2_native(twos, pk [2]uint64) int16 {
- if twos[0] == pk[0] {
- return 0
- }
- if twos[1] == pk[1] {
- return 1
- }
- return 2
- }
- //nolint:unused
- func cmp4_native(fours, pk [4]uint64) int16 {
- for i := range fours {
- if fours[i] >= pk[i] {
- return int16(i)
- }
- }
- return 4
- }
- //nolint:unused
- func cmp8_native(a [8]uint64, pk [4]uint64) int16 {
- for i := range a {
- if a[i] >= pk[0] {
- return int16(i)
- }
- }
- return 8
- }
|