github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/encoding/delta/length_byte_array_amd64.go (about)

     1  //go:build !purego
     2  
     3  package delta
     4  
     5  import (
     6  	"github.com/vc42/parquet-go/encoding/plain"
     7  	"golang.org/x/sys/cpu"
     8  )
     9  
    10  //go:noescape
    11  func validateLengthValuesAVX2(lengths []int32) (totalLength int, ok bool)
    12  
    13  func validateLengthValues(lengths []int32, maxLength int) (totalLength int, err error) {
    14  	if cpu.X86.HasAVX2 {
    15  		totalLength, ok := validateLengthValuesAVX2(lengths)
    16  		if ok {
    17  			return totalLength, nil
    18  		}
    19  	}
    20  
    21  	for i := range lengths {
    22  		n := int(lengths[i])
    23  		if n < 0 {
    24  			return 0, errInvalidNegativeValueLength(n)
    25  		}
    26  		if n > maxLength {
    27  			return 0, errValueLengthOutOfBounds(n, maxLength)
    28  		}
    29  		totalLength += n
    30  	}
    31  
    32  	if totalLength > maxLength {
    33  		err = errValueLengthOutOfBounds(totalLength, maxLength)
    34  	}
    35  	return totalLength, err
    36  }
    37  
    38  //go:noescape
    39  func decodeLengthByteArrayAVX2(dst, src []byte, lengths []int32) int
    40  
    41  func decodeLengthByteArray(dst, src []byte, lengths []int32) ([]byte, error) {
    42  	totalLength, err := validateLengthValues(lengths, len(src))
    43  	if err != nil {
    44  		return dst, err
    45  	}
    46  
    47  	size := plain.ByteArrayLengthSize * len(lengths)
    48  	size += totalLength
    49  	src = src[:totalLength]
    50  	dst = resizeNoMemclr(dst, size+padding)
    51  
    52  	i := 0
    53  	j := 0
    54  	k := 0
    55  	n := 0
    56  
    57  	// To leverage the SEE optimized implementation of the function we must
    58  	// create enough padding at the end to prevent the opportunistic reads
    59  	// and writes from overflowing past the buffer's limits.
    60  	if cpu.X86.HasAVX2 && len(src) > padding {
    61  		k = len(lengths)
    62  
    63  		for k > 0 && n < padding {
    64  			k--
    65  			n += int(lengths[k])
    66  		}
    67  
    68  		if k > 0 && n >= padding {
    69  			i = decodeLengthByteArrayAVX2(dst, src, lengths[:k])
    70  			j = len(src) - n
    71  		} else {
    72  			k = 0
    73  		}
    74  	}
    75  
    76  	for _, n := range lengths[k:] {
    77  		plain.PutByteArrayLength(dst[i:], int(n))
    78  		i += plain.ByteArrayLengthSize
    79  		i += copy(dst[i:], src[j:j+int(n)])
    80  		j += int(n)
    81  	}
    82  
    83  	return dst[:size], nil
    84  }