github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/tpl/math/math.go (about)

     1  // Copyright 2017 The Hugo Authors. All rights reserved.
     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  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  // Package math provides template functions for mathematical operations.
    15  package math
    16  
    17  import (
    18  	"errors"
    19  	"math"
    20  
    21  	_math "github.com/gohugoio/hugo/common/math"
    22  
    23  	"github.com/spf13/cast"
    24  )
    25  
    26  // New returns a new instance of the math-namespaced template functions.
    27  func New() *Namespace {
    28  	return &Namespace{}
    29  }
    30  
    31  // Namespace provides template functions for the "math" namespace.
    32  type Namespace struct{}
    33  
    34  // Add adds two numbers.
    35  func (ns *Namespace) Add(a, b interface{}) (interface{}, error) {
    36  	return _math.DoArithmetic(a, b, '+')
    37  }
    38  
    39  // Ceil returns the least integer value greater than or equal to x.
    40  func (ns *Namespace) Ceil(x interface{}) (float64, error) {
    41  	xf, err := cast.ToFloat64E(x)
    42  	if err != nil {
    43  		return 0, errors.New("Ceil operator can't be used with non-float value")
    44  	}
    45  
    46  	return math.Ceil(xf), nil
    47  }
    48  
    49  // Div divides two numbers.
    50  func (ns *Namespace) Div(a, b interface{}) (interface{}, error) {
    51  	return _math.DoArithmetic(a, b, '/')
    52  }
    53  
    54  // Floor returns the greatest integer value less than or equal to x.
    55  func (ns *Namespace) Floor(x interface{}) (float64, error) {
    56  	xf, err := cast.ToFloat64E(x)
    57  	if err != nil {
    58  		return 0, errors.New("Floor operator can't be used with non-float value")
    59  	}
    60  
    61  	return math.Floor(xf), nil
    62  }
    63  
    64  // Log returns the natural logarithm of a number.
    65  func (ns *Namespace) Log(a interface{}) (float64, error) {
    66  	af, err := cast.ToFloat64E(a)
    67  	if err != nil {
    68  		return 0, errors.New("Log operator can't be used with non integer or float value")
    69  	}
    70  
    71  	return math.Log(af), nil
    72  }
    73  
    74  // Max returns the greater of two numbers.
    75  func (ns *Namespace) Max(a, b interface{}) (float64, error) {
    76  	af, erra := cast.ToFloat64E(a)
    77  	bf, errb := cast.ToFloat64E(b)
    78  
    79  	if erra != nil || errb != nil {
    80  		return 0, errors.New("Max operator can't be used with non-float value")
    81  	}
    82  
    83  	return math.Max(af, bf), nil
    84  }
    85  
    86  // Min returns the smaller of two numbers.
    87  func (ns *Namespace) Min(a, b interface{}) (float64, error) {
    88  	af, erra := cast.ToFloat64E(a)
    89  	bf, errb := cast.ToFloat64E(b)
    90  
    91  	if erra != nil || errb != nil {
    92  		return 0, errors.New("Min operator can't be used with non-float value")
    93  	}
    94  
    95  	return math.Min(af, bf), nil
    96  }
    97  
    98  // Mod returns a % b.
    99  func (ns *Namespace) Mod(a, b interface{}) (int64, error) {
   100  	ai, erra := cast.ToInt64E(a)
   101  	bi, errb := cast.ToInt64E(b)
   102  
   103  	if erra != nil || errb != nil {
   104  		return 0, errors.New("modulo operator can't be used with non integer value")
   105  	}
   106  
   107  	if bi == 0 {
   108  		return 0, errors.New("the number can't be divided by zero at modulo operation")
   109  	}
   110  
   111  	return ai % bi, nil
   112  }
   113  
   114  // ModBool returns the boolean of a % b.  If a % b == 0, return true.
   115  func (ns *Namespace) ModBool(a, b interface{}) (bool, error) {
   116  	res, err := ns.Mod(a, b)
   117  	if err != nil {
   118  		return false, err
   119  	}
   120  
   121  	return res == int64(0), nil
   122  }
   123  
   124  // Mul multiplies two numbers.
   125  func (ns *Namespace) Mul(a, b interface{}) (interface{}, error) {
   126  	return _math.DoArithmetic(a, b, '*')
   127  }
   128  
   129  // Pow returns a raised to the power of b.
   130  func (ns *Namespace) Pow(a, b interface{}) (float64, error) {
   131  	af, erra := cast.ToFloat64E(a)
   132  	bf, errb := cast.ToFloat64E(b)
   133  
   134  	if erra != nil || errb != nil {
   135  		return 0, errors.New("Pow operator can't be used with non-float value")
   136  	}
   137  
   138  	return math.Pow(af, bf), nil
   139  }
   140  
   141  // Round returns the nearest integer, rounding half away from zero.
   142  func (ns *Namespace) Round(x interface{}) (float64, error) {
   143  	xf, err := cast.ToFloat64E(x)
   144  	if err != nil {
   145  		return 0, errors.New("Round operator can't be used with non-float value")
   146  	}
   147  
   148  	return _round(xf), nil
   149  }
   150  
   151  // Sqrt returns the square root of a number.
   152  func (ns *Namespace) Sqrt(a interface{}) (float64, error) {
   153  	af, err := cast.ToFloat64E(a)
   154  	if err != nil {
   155  		return 0, errors.New("Sqrt operator can't be used with non integer or float value")
   156  	}
   157  
   158  	return math.Sqrt(af), nil
   159  }
   160  
   161  // Sub subtracts two numbers.
   162  func (ns *Namespace) Sub(a, b interface{}) (interface{}, error) {
   163  	return _math.DoArithmetic(a, b, '-')
   164  }