numeric.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package sprig
  2. import (
  3. "fmt"
  4. "math"
  5. "reflect"
  6. "strconv"
  7. )
  8. // toFloat64 converts 64-bit floats
  9. func toFloat64(v interface{}) float64 {
  10. if str, ok := v.(string); ok {
  11. iv, err := strconv.ParseFloat(str, 64)
  12. if err != nil {
  13. return 0
  14. }
  15. return iv
  16. }
  17. val := reflect.Indirect(reflect.ValueOf(v))
  18. switch val.Kind() {
  19. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
  20. return float64(val.Int())
  21. case reflect.Uint8, reflect.Uint16, reflect.Uint32:
  22. return float64(val.Uint())
  23. case reflect.Uint, reflect.Uint64:
  24. return float64(val.Uint())
  25. case reflect.Float32, reflect.Float64:
  26. return val.Float()
  27. case reflect.Bool:
  28. if val.Bool() == true {
  29. return 1
  30. }
  31. return 0
  32. default:
  33. return 0
  34. }
  35. }
  36. func toInt(v interface{}) int {
  37. //It's not optimal. Bud I don't want duplicate toInt64 code.
  38. return int(toInt64(v))
  39. }
  40. // toInt64 converts integer types to 64-bit integers
  41. func toInt64(v interface{}) int64 {
  42. if str, ok := v.(string); ok {
  43. iv, err := strconv.ParseInt(str, 10, 64)
  44. if err != nil {
  45. return 0
  46. }
  47. return iv
  48. }
  49. val := reflect.Indirect(reflect.ValueOf(v))
  50. switch val.Kind() {
  51. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
  52. return val.Int()
  53. case reflect.Uint8, reflect.Uint16, reflect.Uint32:
  54. return int64(val.Uint())
  55. case reflect.Uint, reflect.Uint64:
  56. tv := val.Uint()
  57. if tv <= math.MaxInt64 {
  58. return int64(tv)
  59. }
  60. // TODO: What is the sensible thing to do here?
  61. return math.MaxInt64
  62. case reflect.Float32, reflect.Float64:
  63. return int64(val.Float())
  64. case reflect.Bool:
  65. if val.Bool() == true {
  66. return 1
  67. }
  68. return 0
  69. default:
  70. return 0
  71. }
  72. }
  73. func max(a interface{}, i ...interface{}) int64 {
  74. aa := toInt64(a)
  75. for _, b := range i {
  76. bb := toInt64(b)
  77. if bb > aa {
  78. aa = bb
  79. }
  80. }
  81. return aa
  82. }
  83. func min(a interface{}, i ...interface{}) int64 {
  84. aa := toInt64(a)
  85. for _, b := range i {
  86. bb := toInt64(b)
  87. if bb < aa {
  88. aa = bb
  89. }
  90. }
  91. return aa
  92. }
  93. func until(count int) []int {
  94. step := 1
  95. if count < 0 {
  96. step = -1
  97. }
  98. return untilStep(0, count, step)
  99. }
  100. func untilStep(start, stop, step int) []int {
  101. v := []int{}
  102. if stop < start {
  103. if step >= 0 {
  104. return v
  105. }
  106. for i := start; i > stop; i += step {
  107. v = append(v, i)
  108. }
  109. return v
  110. }
  111. if step <= 0 {
  112. return v
  113. }
  114. for i := start; i < stop; i += step {
  115. v = append(v, i)
  116. }
  117. return v
  118. }
  119. func floor(a interface{}) float64 {
  120. aa := toFloat64(a)
  121. return math.Floor(aa)
  122. }
  123. func ceil(a interface{}) float64 {
  124. aa := toFloat64(a)
  125. return math.Ceil(aa)
  126. }
  127. func round(a interface{}, p int, r_opt ...float64) float64 {
  128. roundOn := .5
  129. if len(r_opt) > 0 {
  130. roundOn = r_opt[0]
  131. }
  132. val := toFloat64(a)
  133. places := toFloat64(p)
  134. var round float64
  135. pow := math.Pow(10, places)
  136. digit := pow * val
  137. _, div := math.Modf(digit)
  138. if div >= roundOn {
  139. round = math.Ceil(digit)
  140. } else {
  141. round = math.Floor(digit)
  142. }
  143. return round / pow
  144. }
  145. // converts unix octal to decimal
  146. func toDecimal(v interface{}) int64 {
  147. result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
  148. if err != nil {
  149. return 0
  150. }
  151. return result
  152. }