github.com/matrixorigin/matrixone@v0.7.0/pkg/vectorize/floor/floor.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package floor 16 17 /* floor package provides floor function for all numeric types(uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64). 18 Floor returns the largest round number that is less than or equal to x. 19 example: 20 floor(12, -1) ----> 10 21 floor(12) ----> 12 22 floor(-12, -1) ----> -20 23 floor(-12, 1) ----> -12 24 floor(12.345) ----> 12 25 floor(12.345, 1) ----> 12.3 26 floor(-12.345, 1) ----> -12.4 27 floor(-12.345, -1) ----> -20 28 floor(-12.345) ----> -13 29 floor function takes one or two parameters as its argument, and the second argument must be a constant. 30 floor(x, N) 31 floor(x) == floor(x, 0) 32 N < 0, N zeroes in front of decimal point 33 N >= 0, floor to the Nth placeholder after decimal point 34 */ 35 36 import ( 37 "math" 38 "strconv" 39 "strings" 40 41 "github.com/matrixorigin/matrixone/pkg/container/types" 42 ) 43 44 var ( 45 FloorUint8 func([]uint8, []uint8, int64) []uint8 46 FloorUint16 func([]uint16, []uint16, int64) []uint16 47 FloorUint32 func([]uint32, []uint32, int64) []uint32 48 FloorUint64 func([]uint64, []uint64, int64) []uint64 49 FloorInt8 func([]int8, []int8, int64) []int8 50 FloorInt16 func([]int16, []int16, int64) []int16 51 FloorInt32 func([]int32, []int32, int64) []int32 52 FloorInt64 func([]int64, []int64, int64) []int64 53 FloorFloat32 func([]float32, []float32, int64) []float32 54 FloorFloat64 func([]float64, []float64, int64) []float64 55 FloorDecimal128 func(int32, []types.Decimal128, []types.Decimal128, int64) []types.Decimal128 56 ) 57 58 var MaxUint8digits = numOfDigits(math.MaxUint8) 59 var MaxUint16digits = numOfDigits(math.MaxUint16) 60 var MaxUint32digits = numOfDigits(math.MaxUint32) 61 var MaxUint64digits = numOfDigits(math.MaxUint64) // 20 62 var MaxInt8digits = numOfDigits(math.MaxInt8) 63 var MaxInt16digits = numOfDigits(math.MaxInt16) 64 var MaxInt32digits = numOfDigits(math.MaxInt32) 65 var MaxInt64digits = numOfDigits(math.MaxInt64) // 19 66 67 func numOfDigits(value uint64) int64 { 68 digits := int64(0) 69 for value > 0 { 70 value /= 10 71 digits++ 72 } 73 return digits 74 } 75 76 // ScaleTable is a lookup array for digits 77 var ScaleTable = [...]uint64{ 78 1, 79 10, 80 100, 81 1000, 82 10000, 83 100000, 84 1000000, 85 10000000, 86 100000000, 87 1000000000, 88 10000000000, 89 100000000000, 90 1000000000000, 91 10000000000000, 92 100000000000000, 93 1000000000000000, 94 10000000000000000, 95 100000000000000000, 96 1000000000000000000, 97 10000000000000000000, // 1 followed by 19 zeros, maxUint64 number has 20 digits, so the max scale is 1 followed by 19 zeroes 98 } 99 100 func init() { 101 FloorUint8 = floorUint8 102 FloorUint16 = floorUint16 103 FloorUint32 = floorUint32 104 FloorUint64 = floorUint64 105 FloorInt8 = floorInt8 106 FloorInt16 = floorInt16 107 FloorInt32 = floorInt32 108 FloorInt64 = floorInt64 109 FloorFloat32 = floorFloat32 110 FloorFloat64 = floorFloat64 111 FloorDecimal128 = floorDecimal128 112 } 113 114 func floorUint8(xs, rs []uint8, digits int64) []uint8 { 115 // maximum uint8 number is 255, so we only need to worry about a few digit cases, 116 switch { 117 case digits >= 0: 118 return xs 119 case digits == -1 || digits == -2: 120 scale := uint8(ScaleTable[-digits]) 121 for i := range xs { 122 rs[i] = xs[i] / scale * scale 123 } 124 case digits <= -MaxUint8digits: 125 for i := range xs { 126 rs[i] = 0 127 } 128 } 129 return rs 130 } 131 132 func floorUint16(xs, rs []uint16, digits int64) []uint16 { 133 switch { 134 case digits >= 0: 135 return xs 136 case digits > -MaxUint16digits: 137 scale := uint16(ScaleTable[-digits]) 138 for i := range xs { 139 rs[i] = xs[i] / scale * scale 140 } 141 case digits <= -MaxUint16digits: 142 for i := range xs { 143 rs[i] = 0 144 } 145 } 146 return rs 147 } 148 149 func floorUint32(xs, rs []uint32, digits int64) []uint32 { 150 switch { 151 case digits >= 0: 152 return xs 153 case digits > -MaxUint32digits: 154 scale := uint32(ScaleTable[-digits]) 155 for i := range xs { 156 rs[i] = xs[i] / scale * scale 157 } 158 case digits <= MaxUint32digits: 159 for i := range xs { 160 rs[i] = 0 161 } 162 } 163 return rs 164 } 165 166 func floorUint64(xs, rs []uint64, digits int64) []uint64 { 167 switch { 168 case digits >= 0: 169 return xs 170 case digits > -MaxUint64digits: 171 scale := ScaleTable[-digits] 172 for i := range xs { 173 rs[i] = xs[i] / scale * scale 174 } 175 case digits <= -MaxUint64digits: 176 for i := range xs { 177 rs[i] = 0 178 } 179 } 180 return rs 181 } 182 183 func floorInt8(xs, rs []int8, digits int64) []int8 { 184 switch { 185 case digits >= 0: 186 return xs 187 case digits == -1 || digits == -2: 188 scale := int8(ScaleTable[-digits]) 189 for i := range xs { 190 value := xs[i] 191 if value < 0 { 192 value -= scale - 1 193 } 194 rs[i] = value / scale * scale 195 } 196 case digits <= -MaxInt8digits: 197 for i := range xs { 198 rs[i] = 0 199 } 200 } 201 return rs 202 } 203 204 func floorInt16(xs, rs []int16, digits int64) []int16 { 205 switch { 206 case digits >= 0: 207 return xs 208 case digits > -MaxInt16digits: 209 scale := int16(ScaleTable[-digits]) 210 for i := range xs { 211 value := xs[i] 212 if value < 0 { 213 value -= scale - 1 214 } 215 rs[i] = value / scale * scale 216 } 217 case digits <= -MaxInt16digits: 218 for i := range xs { 219 rs[i] = 0 220 } 221 } 222 return rs 223 } 224 225 func floorInt32(xs, rs []int32, digits int64) []int32 { 226 switch { 227 case digits >= 0: 228 return xs 229 case digits > -MaxInt32digits: 230 scale := int32(ScaleTable[-digits]) 231 for i := range xs { 232 value := xs[i] 233 if value < 0 { 234 value -= scale - 1 235 } 236 rs[i] = value / scale * scale 237 } 238 case digits <= -MaxInt32digits: 239 for i := range xs { 240 rs[i] = 0 241 } 242 } 243 return rs 244 } 245 246 func floorInt64(xs, rs []int64, digits int64) []int64 { 247 switch { 248 case digits >= 0: 249 return xs 250 case digits > -MaxInt64digits: 251 scale := int64(ScaleTable[-digits]) 252 for i := range xs { 253 value := xs[i] 254 if value < 0 { 255 value -= scale - 1 256 } 257 rs[i] = value / scale * scale 258 } 259 case digits <= -MaxInt64digits: 260 for i := range xs { 261 rs[i] = 0 262 } 263 } 264 return rs 265 } 266 267 func floorFloat32(xs, rs []float32, digits int64) []float32 { 268 if digits == 0 { 269 for i := range xs { 270 rs[i] = float32(math.Floor(float64(xs[i]))) 271 } 272 } else { 273 scale := float32(math.Pow10(int(digits))) 274 for i := range xs { 275 value := xs[i] * scale 276 rs[i] = float32(math.Floor(float64(value))) / scale 277 } 278 } 279 return rs 280 } 281 282 func floorFloat64(xs, rs []float64, digits int64) []float64 { 283 if digits == 0 { 284 for i := range xs { 285 rs[i] = math.Floor(xs[i]) 286 } 287 } else { 288 scale := math.Pow10(int(digits)) 289 for i := range xs { 290 value := xs[i] * scale 291 rs[i] = math.Floor(value) / scale 292 } 293 } 294 return rs 295 } 296 297 func floorDecimal128(scale int32, xs, rs []types.Decimal128, _ int64) []types.Decimal128 { 298 for i := range xs { 299 strs := strings.Split(xs[i].ToStringWithScale(scale), ".") 300 x, _ := types.Decimal128_FromString(strs[0]) 301 if strs[0][0] != '-' || len(strs) == 1 { 302 rs[i] = x 303 continue 304 } 305 v, _ := strconv.ParseFloat(strs[1], 64) 306 if v > float64(0) { 307 x = x.AddInt64(-1) 308 } 309 rs[i] = x 310 } 311 return rs 312 }