hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

math.go (4923B)

    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 	"sync/atomic"
   21 
   22 	_math "github.com/gohugoio/hugo/common/math"
   23 
   24 	"github.com/spf13/cast"
   25 )
   26 
   27 // New returns a new instance of the math-namespaced template functions.
   28 func New() *Namespace {
   29 	return &Namespace{}
   30 }
   31 
   32 // Namespace provides template functions for the "math" namespace.
   33 type Namespace struct{}
   34 
   35 // Add adds the two addends n1 and n2.
   36 func (ns *Namespace) Add(n1, n2 any) (any, error) {
   37 	return _math.DoArithmetic(n1, n2, '+')
   38 }
   39 
   40 // Ceil returns the least integer value greater than or equal to n.
   41 func (ns *Namespace) Ceil(n any) (float64, error) {
   42 	xf, err := cast.ToFloat64E(n)
   43 	if err != nil {
   44 		return 0, errors.New("Ceil operator can't be used with non-float value")
   45 	}
   46 
   47 	return math.Ceil(xf), nil
   48 }
   49 
   50 // Div divides n1 by n2.
   51 func (ns *Namespace) Div(n1, n2 any) (any, error) {
   52 	return _math.DoArithmetic(n1, n2, '/')
   53 }
   54 
   55 // Floor returns the greatest integer value less than or equal to n.
   56 func (ns *Namespace) Floor(n any) (float64, error) {
   57 	xf, err := cast.ToFloat64E(n)
   58 	if err != nil {
   59 		return 0, errors.New("Floor operator can't be used with non-float value")
   60 	}
   61 
   62 	return math.Floor(xf), nil
   63 }
   64 
   65 // Log returns the natural logarithm of the number n.
   66 func (ns *Namespace) Log(n any) (float64, error) {
   67 	af, err := cast.ToFloat64E(n)
   68 	if err != nil {
   69 		return 0, errors.New("Log operator can't be used with non integer or float value")
   70 	}
   71 
   72 	return math.Log(af), nil
   73 }
   74 
   75 // Max returns the greater of the two numbers n1 or n2.
   76 func (ns *Namespace) Max(n1, n2 any) (float64, error) {
   77 	af, erra := cast.ToFloat64E(n1)
   78 	bf, errb := cast.ToFloat64E(n2)
   79 
   80 	if erra != nil || errb != nil {
   81 		return 0, errors.New("Max operator can't be used with non-float value")
   82 	}
   83 
   84 	return math.Max(af, bf), nil
   85 }
   86 
   87 // Min returns the smaller of two numbers n1 or n2.
   88 func (ns *Namespace) Min(n1, n2 any) (float64, error) {
   89 	af, erra := cast.ToFloat64E(n1)
   90 	bf, errb := cast.ToFloat64E(n2)
   91 
   92 	if erra != nil || errb != nil {
   93 		return 0, errors.New("Min operator can't be used with non-float value")
   94 	}
   95 
   96 	return math.Min(af, bf), nil
   97 }
   98 
   99 // Mod returns n1 % n2.
  100 func (ns *Namespace) Mod(n1, n2 any) (int64, error) {
  101 	ai, erra := cast.ToInt64E(n1)
  102 	bi, errb := cast.ToInt64E(n2)
  103 
  104 	if erra != nil || errb != nil {
  105 		return 0, errors.New("modulo operator can't be used with non integer value")
  106 	}
  107 
  108 	if bi == 0 {
  109 		return 0, errors.New("the number can't be divided by zero at modulo operation")
  110 	}
  111 
  112 	return ai % bi, nil
  113 }
  114 
  115 // ModBool returns the boolean of n1 % n2.  If n1 % n2 == 0, return true.
  116 func (ns *Namespace) ModBool(n1, n2 any) (bool, error) {
  117 	res, err := ns.Mod(n1, n2)
  118 	if err != nil {
  119 		return false, err
  120 	}
  121 
  122 	return res == int64(0), nil
  123 }
  124 
  125 // Mul multiplies the two numbers n1 and n2.
  126 func (ns *Namespace) Mul(n1, n2 any) (any, error) {
  127 	return _math.DoArithmetic(n1, n2, '*')
  128 }
  129 
  130 // Pow returns n1 raised to the power of n2.
  131 func (ns *Namespace) Pow(n1, n2 any) (float64, error) {
  132 	af, erra := cast.ToFloat64E(n1)
  133 	bf, errb := cast.ToFloat64E(n2)
  134 
  135 	if erra != nil || errb != nil {
  136 		return 0, errors.New("Pow operator can't be used with non-float value")
  137 	}
  138 
  139 	return math.Pow(af, bf), nil
  140 }
  141 
  142 // Round returns the integer nearest to n, rounding half away from zero.
  143 func (ns *Namespace) Round(n any) (float64, error) {
  144 	xf, err := cast.ToFloat64E(n)
  145 	if err != nil {
  146 		return 0, errors.New("Round operator can't be used with non-float value")
  147 	}
  148 
  149 	return _round(xf), nil
  150 }
  151 
  152 // Sqrt returns the square root of the number n.
  153 func (ns *Namespace) Sqrt(n any) (float64, error) {
  154 	af, err := cast.ToFloat64E(n)
  155 	if err != nil {
  156 		return 0, errors.New("Sqrt operator can't be used with non integer or float value")
  157 	}
  158 
  159 	return math.Sqrt(af), nil
  160 }
  161 
  162 // Sub subtracts n2 from n1.
  163 func (ns *Namespace) Sub(n1, n2 any) (any, error) {
  164 	return _math.DoArithmetic(n1, n2, '-')
  165 }
  166 
  167 var counter uint64
  168 
  169 // Counter increments and returns a global counter.
  170 // This was originally added to be used in tests where now.UnixNano did not
  171 // have the needed precision (especially on Windows).
  172 // Note that given the parallel nature of Hugo, you cannot use this to get sequences of numbers,
  173 // and the counter will reset on new builds.
  174 func (ns *Namespace) Counter() uint64 {
  175 	return atomic.AddUint64(&counter, uint64(1))
  176 }