...

Source file src/github.com/go-task/slim-sprig/v3/numeric.go

Documentation: github.com/go-task/slim-sprig/v3

     1  package sprig
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // toFloat64 converts 64-bit floats
    12  func toFloat64(v interface{}) float64 {
    13  	if str, ok := v.(string); ok {
    14  		iv, err := strconv.ParseFloat(str, 64)
    15  		if err != nil {
    16  			return 0
    17  		}
    18  		return iv
    19  	}
    20  
    21  	val := reflect.Indirect(reflect.ValueOf(v))
    22  	switch val.Kind() {
    23  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
    24  		return float64(val.Int())
    25  	case reflect.Uint8, reflect.Uint16, reflect.Uint32:
    26  		return float64(val.Uint())
    27  	case reflect.Uint, reflect.Uint64:
    28  		return float64(val.Uint())
    29  	case reflect.Float32, reflect.Float64:
    30  		return val.Float()
    31  	case reflect.Bool:
    32  		if val.Bool() {
    33  			return 1
    34  		}
    35  		return 0
    36  	default:
    37  		return 0
    38  	}
    39  }
    40  
    41  func toInt(v interface{}) int {
    42  	//It's not optimal. Bud I don't want duplicate toInt64 code.
    43  	return int(toInt64(v))
    44  }
    45  
    46  // toInt64 converts integer types to 64-bit integers
    47  func toInt64(v interface{}) int64 {
    48  	if str, ok := v.(string); ok {
    49  		iv, err := strconv.ParseInt(str, 10, 64)
    50  		if err != nil {
    51  			return 0
    52  		}
    53  		return iv
    54  	}
    55  
    56  	val := reflect.Indirect(reflect.ValueOf(v))
    57  	switch val.Kind() {
    58  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
    59  		return val.Int()
    60  	case reflect.Uint8, reflect.Uint16, reflect.Uint32:
    61  		return int64(val.Uint())
    62  	case reflect.Uint, reflect.Uint64:
    63  		tv := val.Uint()
    64  		if tv <= math.MaxInt64 {
    65  			return int64(tv)
    66  		}
    67  		// TODO: What is the sensible thing to do here?
    68  		return math.MaxInt64
    69  	case reflect.Float32, reflect.Float64:
    70  		return int64(val.Float())
    71  	case reflect.Bool:
    72  		if val.Bool() {
    73  			return 1
    74  		}
    75  		return 0
    76  	default:
    77  		return 0
    78  	}
    79  }
    80  
    81  func max(a interface{}, i ...interface{}) int64 {
    82  	aa := toInt64(a)
    83  	for _, b := range i {
    84  		bb := toInt64(b)
    85  		if bb > aa {
    86  			aa = bb
    87  		}
    88  	}
    89  	return aa
    90  }
    91  
    92  func maxf(a interface{}, i ...interface{}) float64 {
    93  	aa := toFloat64(a)
    94  	for _, b := range i {
    95  		bb := toFloat64(b)
    96  		aa = math.Max(aa, bb)
    97  	}
    98  	return aa
    99  }
   100  
   101  func min(a interface{}, i ...interface{}) int64 {
   102  	aa := toInt64(a)
   103  	for _, b := range i {
   104  		bb := toInt64(b)
   105  		if bb < aa {
   106  			aa = bb
   107  		}
   108  	}
   109  	return aa
   110  }
   111  
   112  func minf(a interface{}, i ...interface{}) float64 {
   113  	aa := toFloat64(a)
   114  	for _, b := range i {
   115  		bb := toFloat64(b)
   116  		aa = math.Min(aa, bb)
   117  	}
   118  	return aa
   119  }
   120  
   121  func until(count int) []int {
   122  	step := 1
   123  	if count < 0 {
   124  		step = -1
   125  	}
   126  	return untilStep(0, count, step)
   127  }
   128  
   129  func untilStep(start, stop, step int) []int {
   130  	v := []int{}
   131  
   132  	if stop < start {
   133  		if step >= 0 {
   134  			return v
   135  		}
   136  		for i := start; i > stop; i += step {
   137  			v = append(v, i)
   138  		}
   139  		return v
   140  	}
   141  
   142  	if step <= 0 {
   143  		return v
   144  	}
   145  	for i := start; i < stop; i += step {
   146  		v = append(v, i)
   147  	}
   148  	return v
   149  }
   150  
   151  func floor(a interface{}) float64 {
   152  	aa := toFloat64(a)
   153  	return math.Floor(aa)
   154  }
   155  
   156  func ceil(a interface{}) float64 {
   157  	aa := toFloat64(a)
   158  	return math.Ceil(aa)
   159  }
   160  
   161  func round(a interface{}, p int, rOpt ...float64) float64 {
   162  	roundOn := .5
   163  	if len(rOpt) > 0 {
   164  		roundOn = rOpt[0]
   165  	}
   166  	val := toFloat64(a)
   167  	places := toFloat64(p)
   168  
   169  	var round float64
   170  	pow := math.Pow(10, places)
   171  	digit := pow * val
   172  	_, div := math.Modf(digit)
   173  	if div >= roundOn {
   174  		round = math.Ceil(digit)
   175  	} else {
   176  		round = math.Floor(digit)
   177  	}
   178  	return round / pow
   179  }
   180  
   181  // converts unix octal to decimal
   182  func toDecimal(v interface{}) int64 {
   183  	result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
   184  	if err != nil {
   185  		return 0
   186  	}
   187  	return result
   188  }
   189  
   190  func seq(params ...int) string {
   191  	increment := 1
   192  	switch len(params) {
   193  	case 0:
   194  		return ""
   195  	case 1:
   196  		start := 1
   197  		end := params[0]
   198  		if end < start {
   199  			increment = -1
   200  		}
   201  		return intArrayToString(untilStep(start, end+increment, increment), " ")
   202  	case 3:
   203  		start := params[0]
   204  		end := params[2]
   205  		step := params[1]
   206  		if end < start {
   207  			increment = -1
   208  			if step > 0 {
   209  				return ""
   210  			}
   211  		}
   212  		return intArrayToString(untilStep(start, end+increment, step), " ")
   213  	case 2:
   214  		start := params[0]
   215  		end := params[1]
   216  		step := 1
   217  		if end < start {
   218  			step = -1
   219  		}
   220  		return intArrayToString(untilStep(start, end+step, step), " ")
   221  	default:
   222  		return ""
   223  	}
   224  }
   225  
   226  func intArrayToString(slice []int, delimeter string) string {
   227  	return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(slice)), delimeter), "[]")
   228  }
   229  

View as plain text