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  }