github.com/segmentio/parquet-go@v0.0.0-20230712180008-5d42db8f0d47/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 // Int32ToInt96 converts a int32 value to a Int96. 13 func Int32ToInt96(value int32) (i96 Int96) { 14 if value < 0 { 15 i96[2] = 0xFFFFFFFF 16 i96[1] = 0xFFFFFFFF 17 } 18 i96[0] = uint32(value) 19 return 20 } 21 22 // Int64ToInt96 converts a int64 value to Int96. 23 func Int64ToInt96(value int64) (i96 Int96) { 24 if value < 0 { 25 i96[2] = 0xFFFFFFFF 26 } 27 i96[1] = uint32(value >> 32) 28 i96[0] = uint32(value) 29 return 30 } 31 32 // IsZero returns true if i is the zero-value. 33 func (i Int96) IsZero() bool { return i == Int96{} } 34 35 // Negative returns true if i is a negative value. 36 func (i Int96) Negative() bool { 37 return (i[2] >> 31) != 0 38 } 39 40 // Less returns true if i < j. 41 // 42 // The method implements a signed comparison between the two operands. 43 func (i Int96) Less(j Int96) bool { 44 if i.Negative() { 45 if !j.Negative() { 46 return true 47 } 48 } else { 49 if j.Negative() { 50 return false 51 } 52 } 53 for k := 2; k >= 0; k-- { 54 a, b := i[k], j[k] 55 switch { 56 case a < b: 57 return true 58 case a > b: 59 return false 60 } 61 } 62 return false 63 } 64 65 // Int converts i to a big.Int representation. 66 func (i Int96) Int() *big.Int { 67 z := new(big.Int) 68 z.Or(z, big.NewInt(int64(i[2])<<32|int64(i[1]))) 69 z.Lsh(z, 32) 70 z.Or(z, big.NewInt(int64(i[0]))) 71 return z 72 } 73 74 // Int32 converts i to a int32, potentially truncating the value. 75 func (i Int96) Int32() int32 { 76 return int32(i[0]) 77 } 78 79 // Int64 converts i to a int64, potentially truncating the value. 80 func (i Int96) Int64() int64 { 81 return int64(i[1])<<32 | int64(i[0]) 82 } 83 84 // String returns a string representation of i. 85 func (i Int96) String() string { 86 return i.Int().String() 87 } 88 89 // Len returns the minimum length in bits required to store the value of i. 90 func (i Int96) Len() int { 91 switch { 92 case i[2] != 0: 93 return 64 + bits.Len32(i[2]) 94 case i[1] != 0: 95 return 32 + bits.Len32(i[1]) 96 default: 97 return bits.Len32(i[0]) 98 } 99 } 100 101 // Int96ToBytes converts the slice of Int96 values to a slice of bytes sharing 102 // the same backing array. 103 func Int96ToBytes(data []Int96) []byte { 104 return unsafe.Slice(*(**byte)(unsafe.Pointer(&data)), 12*len(data)) 105 } 106 107 // BytesToInt96 converts the byte slice passed as argument to a slice of Int96 108 // sharing the same backing array. 109 // 110 // When the number of bytes in the input is not a multiple of 12, the function 111 // truncates it in the returned slice. 112 func BytesToInt96(data []byte) []Int96 { 113 return unsafe.Slice(*(**Int96)(unsafe.Pointer(&data)), len(data)/12) 114 } 115 116 func MaxLenInt96(data []Int96) int { 117 max := 0 118 for i := range data { 119 n := data[i].Len() 120 if n > max { 121 max = n 122 } 123 } 124 return max 125 } 126 127 func MinInt96(data []Int96) (min Int96) { 128 if len(data) > 0 { 129 min = data[0] 130 for _, v := range data[1:] { 131 if v.Less(min) { 132 min = v 133 } 134 } 135 } 136 return min 137 } 138 139 func MaxInt96(data []Int96) (max Int96) { 140 if len(data) > 0 { 141 max = data[0] 142 for _, v := range data[1:] { 143 if max.Less(v) { 144 max = v 145 } 146 } 147 } 148 return max 149 } 150 151 func MinMaxInt96(data []Int96) (min, max Int96) { 152 if len(data) > 0 { 153 min = data[0] 154 max = data[0] 155 for _, v := range data[1:] { 156 if v.Less(min) { 157 min = v 158 } 159 if max.Less(v) { 160 max = v 161 } 162 } 163 } 164 return min, max 165 } 166 167 func OrderOfInt96(data []Int96) int { 168 if len(data) > 1 { 169 if int96AreInAscendingOrder(data) { 170 return +1 171 } 172 if int96AreInDescendingOrder(data) { 173 return -1 174 } 175 } 176 return 0 177 } 178 179 func int96AreInAscendingOrder(data []Int96) bool { 180 for i := len(data) - 1; i > 0; i-- { 181 if data[i].Less(data[i-1]) { 182 return false 183 } 184 } 185 return true 186 } 187 188 func int96AreInDescendingOrder(data []Int96) bool { 189 for i := len(data) - 1; i > 0; i-- { 190 if data[i-1].Less(data[i]) { 191 return false 192 } 193 } 194 return true 195 }