github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/deprecated/int96.go (about)

     1  package deprecated
     2  
     3  import (
     4  	"math/big"
     5  	"math/bits"
     6  	"unsafe"
     7  )
     8  
     9  // Int96 is an implementation of the deprecated INT96 parquet type.
    10  type Int96 [3]uint32
    11  
    12  // Negative returns true if i is a negative value.
    13  func (i Int96) Negative() bool {
    14  	return (i[2] >> 31) != 0
    15  }
    16  
    17  // Less returns true if i < j.
    18  //
    19  // The method implements a signed comparison between the two operands.
    20  func (i Int96) Less(j Int96) bool {
    21  	if i.Negative() {
    22  		if !j.Negative() {
    23  			return true
    24  		}
    25  	} else {
    26  		if j.Negative() {
    27  			return false
    28  		}
    29  	}
    30  	for k := 2; k >= 0; k-- {
    31  		a, b := i[k], j[k]
    32  		switch {
    33  		case a < b:
    34  			return true
    35  		case a > b:
    36  			return false
    37  		}
    38  	}
    39  	return false
    40  }
    41  
    42  // Int converts i to a big.Int representation.
    43  func (i Int96) Int() *big.Int {
    44  	z := new(big.Int)
    45  	z.Or(z, big.NewInt(int64(i[2])<<32|int64(i[1])))
    46  	z.Lsh(z, 32)
    47  	z.Or(z, big.NewInt(int64(i[0])))
    48  	return z
    49  }
    50  
    51  // String returns a string representation of i.
    52  func (i Int96) String() string {
    53  	return i.Int().String()
    54  }
    55  
    56  // Len returns the minimum length in bits required to store the value of i.
    57  func (i Int96) Len() int {
    58  	switch {
    59  	case i[2] != 0:
    60  		return 64 + bits.Len32(i[2])
    61  	case i[1] != 0:
    62  		return 32 + bits.Len32(i[1])
    63  	default:
    64  		return bits.Len32(i[0])
    65  	}
    66  }
    67  
    68  // Int96ToBytes converts the slice of Int96 values to a slice of bytes sharing
    69  // the same backing array.
    70  func Int96ToBytes(data []Int96) []byte {
    71  	return unsafe.Slice(*(**byte)(unsafe.Pointer(&data)), 12*len(data))
    72  }
    73  
    74  // BytesToInt96 converts the byte slice passed as argument to a slice of Int96
    75  // sharing the same backing array.
    76  //
    77  // When the number of bytes in the input is not a multiple of 12, the function
    78  // truncates it in the returned slice.
    79  func BytesToInt96(data []byte) []Int96 {
    80  	return unsafe.Slice(*(**Int96)(unsafe.Pointer(&data)), len(data)/12)
    81  }
    82  
    83  func MaxLenInt96(data []Int96) int {
    84  	max := 0
    85  	for i := range data {
    86  		n := data[i].Len()
    87  		if n > max {
    88  			max = n
    89  		}
    90  	}
    91  	return max
    92  }
    93  
    94  func MinInt96(data []Int96) (min Int96) {
    95  	if len(data) > 0 {
    96  		min = data[0]
    97  		for _, v := range data[1:] {
    98  			if v.Less(min) {
    99  				min = v
   100  			}
   101  		}
   102  	}
   103  	return min
   104  }
   105  
   106  func MaxInt96(data []Int96) (max Int96) {
   107  	if len(data) > 0 {
   108  		max = data[0]
   109  		for _, v := range data[1:] {
   110  			if max.Less(v) {
   111  				max = v
   112  			}
   113  		}
   114  	}
   115  	return max
   116  }
   117  
   118  func MinMaxInt96(data []Int96) (min, max Int96) {
   119  	if len(data) > 0 {
   120  		min = data[0]
   121  		max = data[0]
   122  		for _, v := range data[1:] {
   123  			if v.Less(min) {
   124  				min = v
   125  			}
   126  			if max.Less(v) {
   127  				max = v
   128  			}
   129  		}
   130  	}
   131  	return min, max
   132  }
   133  
   134  func OrderOfInt96(data []Int96) int {
   135  	if len(data) > 1 {
   136  		if int96AreInAscendingOrder(data) {
   137  			return +1
   138  		}
   139  		if int96AreInDescendingOrder(data) {
   140  			return -1
   141  		}
   142  	}
   143  	return 0
   144  }
   145  
   146  func int96AreInAscendingOrder(data []Int96) bool {
   147  	for i := len(data) - 1; i > 0; i-- {
   148  		if data[i].Less(data[i-1]) {
   149  			return false
   150  		}
   151  	}
   152  	return true
   153  }
   154  
   155  func int96AreInDescendingOrder(data []Int96) bool {
   156  	for i := len(data) - 1; i > 0; i-- {
   157  		if data[i-1].Less(data[i]) {
   158  			return false
   159  		}
   160  	}
   161  	return true
   162  }