Source file src/simd/archsimd/slicepart_arm64.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build goexperiment.simd && arm64
     6  
     7  package archsimd
     8  
     9  import "unsafe"
    10  
    11  // LoadUint32x4Part loads a Int32x4 from the slice s.
    12  // If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
    13  // If s has 4 or more elements, the function is equivalent to LoadUint32x4.
    14  func LoadUint32x4Part(s []uint32) (Uint32x4, int) {
    15  	l := len(s)
    16  	if l >= 4 {
    17  		return LoadUint32x4(s), 4
    18  	}
    19  	var x Uint32x4
    20  	if l == 0 {
    21  		return x, 0
    22  	}
    23  	if l >= 2 { // 2,3
    24  		x = x.ReshapeToUint64s().SetElem(0, *uint64atP32(&s[0])).ReshapeToUint32s()
    25  		if l == 3 {
    26  			x = x.SetElem(2, s[2])
    27  		}
    28  	} else { // l == 1
    29  		x = x.SetElem(0, s[0])
    30  	}
    31  	return x, l
    32  }
    33  
    34  // StorePart stores the elements of x into the slice s.
    35  // It stores as many elements as will fit in s.
    36  // If s has 4 or more elements, the method is equivalent to x.Store.
    37  func (x Uint32x4) StorePart(s []uint32) int {
    38  	l := len(s)
    39  	if l >= 4 {
    40  		x.Store(s)
    41  		return 4
    42  	}
    43  	if l == 0 {
    44  		return 0
    45  	}
    46  	if l >= 2 { // 2,3
    47  		*uint64atP32(&s[0]) = x.ReshapeToUint64s().GetElem(0)
    48  		if l == 3 {
    49  			s[2] = x.GetElem(2)
    50  		}
    51  	} else { // l == 1
    52  		s[0] = x.GetElem(0)
    53  	}
    54  	return l
    55  }
    56  
    57  // LoadUint64x2Part loads a Int64x2 from the slice s.
    58  // If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
    59  // If s has 2 or more elements, the function is equivalent to LoadUint64x2.
    60  func LoadUint64x2Part(s []uint64) (Uint64x2, int) {
    61  	l := len(s)
    62  	if l >= 2 {
    63  		return LoadUint64x2(s), 2
    64  	}
    65  	var x Uint64x2
    66  	if l == 0 {
    67  		return x, 0
    68  	}
    69  	// l == 1
    70  	x = x.SetElem(0, s[0])
    71  	return x, 1
    72  }
    73  
    74  // StorePart stores the elements of x into the slice s.
    75  // It stores as many elements as will fit in s.
    76  // If s has 2 or more elements, the method is equivalent to x.Store.
    77  func (x Uint64x2) StorePart(s []uint64) int {
    78  	l := len(s)
    79  	if l >= 2 {
    80  		x.Store(s)
    81  		return 2
    82  	}
    83  	if l == 0 {
    84  		return 0
    85  	}
    86  	// l == 1
    87  	s[0] = x.GetElem(0)
    88  	return 1
    89  }
    90  
    91  // LoadInt32x4Part loads a Int32x4 from the slice s.
    92  // If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
    93  // If s has 4 or more elements, the function is equivalent to LoadInt32x4.
    94  func LoadInt32x4Part(s []int32) (Int32x4, int) {
    95  	if len(s) == 0 {
    96  		var zero Int32x4
    97  		return zero, 0
    98  	}
    99  	t := unsafe.Slice((*uint32)(unsafe.Pointer(&s[0])), len(s))
   100  	v, l := LoadUint32x4Part(t)
   101  	return v.BitsToInt32(), l
   102  }
   103  
   104  // StorePart stores the 4 elements of x into the slice s.
   105  // It stores as many elements as will fit in s.
   106  // If s has 4 or more elements, the method is equivalent to x.Store.
   107  func (x Int32x4) StorePart(s []int32) int {
   108  	if len(s) == 0 {
   109  		return 0
   110  	}
   111  	t := unsafe.Slice((*uint32)(unsafe.Pointer(&s[0])), len(s))
   112  	return x.ToBits().StorePart(t)
   113  }
   114  
   115  // LoadInt64x2Part loads a Int64x2 from the slice s.
   116  // If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
   117  // If s has 2 or more elements, the function is equivalent to LoadInt64x2.
   118  func LoadInt64x2Part(s []int64) (Int64x2, int) {
   119  	if len(s) == 0 {
   120  		var zero Int64x2
   121  		return zero, 0
   122  	}
   123  	t := unsafe.Slice((*uint64)(unsafe.Pointer(&s[0])), len(s))
   124  	v, l := LoadUint64x2Part(t)
   125  	return v.BitsToInt64(), l
   126  }
   127  
   128  // StorePart stores the 2 elements of x into the slice s.
   129  // It stores as many elements as will fit in s.
   130  // If s has 2 or more elements, the method is equivalent to x.Store.
   131  func (x Int64x2) StorePart(s []int64) int {
   132  	if len(s) == 0 {
   133  		return 0
   134  	}
   135  	t := unsafe.Slice((*uint64)(unsafe.Pointer(&s[0])), len(s))
   136  	return x.ToBits().StorePart(t)
   137  }
   138  
   139  // LoadFloat32x4Part loads a Float32x4 from the slice s.
   140  // If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
   141  // If s has 4 or more elements, the function is equivalent to LoadFloat32x4.
   142  func LoadFloat32x4Part(s []float32) (Float32x4, int) {
   143  	l := len(s)
   144  	if l >= 4 {
   145  		return LoadFloat32x4(s), 4
   146  	}
   147  	var x Float32x4
   148  	if l == 0 {
   149  		return x, l
   150  	}
   151  	if l >= 2 { // 2,3
   152  		x = x.ToBits().ReshapeToUint64s().BitsToFloat64().SetElem(0, *float64atP32(&s[0])).ToBits().ReshapeToUint32s().BitsToFloat32()
   153  		if l == 3 {
   154  			x = x.SetElem(2, s[2])
   155  		}
   156  	} else { // l == 1
   157  		x = x.SetElem(0, s[0])
   158  	}
   159  	return x, l
   160  }
   161  
   162  // StorePart stores the elements of x into the slice s.
   163  // It stores as many elements as will fit in s.
   164  // If s has 4 or more elements, the method is equivalent to x.Store.
   165  func (x Float32x4) StorePart(s []float32) int {
   166  	l := len(s)
   167  	if l >= 4 {
   168  		x.Store(s)
   169  		return 4
   170  	}
   171  	if l == 0 {
   172  		return 0
   173  	}
   174  	if l >= 2 { // 2,3(
   175  		*float64atP32(&s[0]) = x.ToBits().ReshapeToUint64s().BitsToFloat64().GetElem(0)
   176  		if l == 3 {
   177  			s[2] = x.GetElem(2)
   178  		}
   179  	} else { // l == 1
   180  		s[0] = x.GetElem(0)
   181  	}
   182  	return l
   183  }
   184  
   185  // LoadFloat64x2Part loads a Float64x2 from the slice s.
   186  // If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
   187  // If s has 2 or more elements, the function is equivalent to LoadFloat64x2.
   188  func LoadFloat64x2Part(s []float64) (Float64x2, int) {
   189  	l := len(s)
   190  	if l >= 2 {
   191  		return LoadFloat64x2(s), 2
   192  	}
   193  	var x Float64x2
   194  	if l == 0 {
   195  		return x, l
   196  	}
   197  	// l == 1
   198  	x = x.SetElem(0, s[0])
   199  	return x, l
   200  }
   201  
   202  // StorePart stores the elements of x into the slice s.
   203  // It stores as many elements as will fit in s.
   204  // If s has 2 or more elements, the method is equivalent to x.Store.
   205  func (x Float64x2) StorePart(s []float64) int {
   206  	l := len(s)
   207  	if l >= 2 {
   208  		x.Store(s)
   209  		return 2
   210  	}
   211  	if l == 0 {
   212  		return 0
   213  	}
   214  	// l == 1
   215  	s[0] = x.GetElem(0)
   216  	return l
   217  }
   218  

View as plain text