math

package
v0.0.0-...-fce414a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 5, 2025 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package math provides useful math functions

SPDX-License-Identifier: Apache-2.0

Index

Constants

This section is empty.

Variables

View Source
var (
	OverflowErr  = fmt.Errorf("Overflow error")
	UnderflowErr = fmt.Errorf("Underflow error")
	DivByZeroErr = fmt.Errorf("Division by zero error")
)

Constants

Functions

func Abs

func Abs[T constraint.Numeric](val *T) error

Abs calculates the absolute value of any numeric type. Integer types have a range of -N ... +(N-1), which means that if you try to calculate abs(-N), the result is -N. The reason for this is that there is no corresponding +N, that would require more bits. In this special case, an error is returned, otherwise nil is returned. Note that while the constraint allows unsigned ints for completeness, no operation is performed.

func AddInt

func AddInt[T constraint.SignedInteger](ae1 T, ae2 *T) error

AddInt adds two signed integers overwriting the second value, and returns an error if over/underflow occurs. Over/underflow occurrs if two numbers of the same sign are added, and the sign of result has changed. EG, two positive ints are added to create a result too large to be represented in the same number of bits,

or two negative ints are added to create a result too small to be represented in the same number of bits.

func AddUint

func AddUint[T constraint.UnsignedInteger](ae1 T, ae2 *T) error

AddUint adds two unsigned integers overwriting the second value, and returns an error if overflow occurs. Overflow occurs if two numbers are added, and the magnitude of result is smaller.

func AdjustDecimalFormat

func AdjustDecimalFormat(d1, d2 Decimal) (string, string)

AdjustDecimalFormat adjusts the two decimals strings to have the same number of digits before the decimal, and the same number of digits after the decimal. Leading and trailing zeros are added as needed. A positive number has a leading space.

The strings returned are not directly comparable numerically: "-1" > " 1" "-2" > "-1"

Examples: 30, 5 -> " 30", " 05" 1.23, -78.295 -> " 01.230", "-78.295"

func AdjustDecimalScale

func AdjustDecimalScale(d1, d2 *Decimal) error

AdjustDecimalScale adjusts the scale of d1 and d2:

  • If both numbers have the same scale, no adjustment is made
  • Otherwise, the number with the smaller scale is usually adjusted to the same scale as the other number
  • Increasing the scale can cause some most significant digits to be lost, in which case the other number is rounded down to match the scale

Examples:

1.5 and 1.25 -> 1.50 and 1.25 1.5 and 18 digits with no decimals -> 18 digits cannot increase scale, so round 1.5 to 2 99_999_999_999_999_999.5 and 1 -> the 18 digits round to a 19 digit value, an error occurs

func CmpComplex

func CmpComplex[T constraint.Complex](val1, val2 T) (res int)

CmpComplex compares two complex types and returns -1, 0, 1, depending on whether val1 is <, =, or > val2.

func CmpOrdered

func CmpOrdered[T constraint.Ordered](val1, val2 T) (res int)

CmpOrdered compares two ordered types and returns -1, 0, 1, depending on whether val1 is <, =, or > val2.

func Div

func Div[T constraint.Numeric](dividend T, divisor T, quotient *T) error

Div calculates the quotient of a division operation of a pair of integers or a pair of floating point types. In the case of integers, the remainder is handled as follows: - If the divisor is even, and abs(remainder) >= abs(divisor) / 2, then increase magnitude of quotient by one. - If the divisor is odd, and abs(remainder) > abs(divisor) / 2, then increase magnitude of quotient by one.

Increasing the magnitude by one means add one of the quotient is positive, subtract one if negative. The purpose of adjusting the magnitude is to get the same result as rounding the floating point calculation. Floats are not used since 32 and 64 bit integer values can have a magnitude too large to be expressed accurately in a float.

Integer Examples: 18 / 4 = 4 remainder 2. Since divisor 4 is even and remainder 2 is >= (4 / 2 = 2), increment quotient to 5 (round 4.5 up). 17 / 5 = 3 remainder 2. Since divisor 5 is odd and remainder 2 is not > (5 / 2 = 2), leave quotient as is (round 3.4 down).

func DivBigOps

func DivBigOps[T constraint.BigOps[T]](dividend T, divisor T, quotient *T) error

DivBigOps is the BigOps version of Div

func MaxCmp

func MaxCmp[T constraint.Cmp[T]](val1, val2 T) T

MaxCmp returns the maximum value of two comparable types

func MaxComplex

func MaxComplex[T constraint.Complex](val1, val2 T) T

MaxComplex returns the maximum value of two complex types

func MaxOrdered

func MaxOrdered[T constraint.Ordered](val1, val2 T) T

MaxOrdered returns the maximum value of two ordered types

func MinCmp

func MinCmp[T constraint.Cmp[T]](val1, val2 T) T

MinCmp returns the minimum value of two comparable types

func MinComplex

func MinComplex[T constraint.Complex](val1, val2 T) T

MinComplex returns the minimum value of two complex types

func MinOrdered

func MinOrdered[T constraint.Ordered](val1, val2 T) T

MinOrdered returns the minimum value of two ordered types

func Mul

func Mul[T constraint.Integer](mp T, ma *T) error

Mul multiples two integers overwriting the second value, and returns an error if over/underflow occurs. Over/underflow occurs if the magnitude of the result requires more bits than the type provides. Unsigned types can only overflow.

func MustAdjustDecimalScale

func MustAdjustDecimalScale(d1, d2 *Decimal)

MustAdjustDecimalScale is a must version of AdjustDecimalScale

func SubInt

func SubInt[T constraint.SignedInteger](me T, sed *T) error

SubInt subtracts two integers as sed = me - sed, overwriting the second value, and returns an error if over/underflow occurs. See AddInt.

func SubUint

func SubUint[T constraint.UnsignedInteger](me T, sed *T) error

SubUint subtracts two integers as sed = me - sed, overwriting the second value, and returns an error if underflow occurs. Underflow occurs if sed > me before the subtraction is performed.

Types

type Decimal

type Decimal struct {
	// contains filtered or unexported fields
}

Decimal is like SQL Decimal(precision, scale): - precision is always 18, the maximum number of decimal digits a signed 64 bit value can store - scale is number of digits after decimal place, must be <= 18 (default 2 as most popular use is money)

The zero value is ready to use

func MustDecimal

func MustDecimal(value int64, scale uint, normalized ...bool) Decimal

MustDecimal is a must version of OfDecimal

func MustStringToDecimal

func MustStringToDecimal(value string) Decimal

MustStringToDecimal is a must version of StringToDecimal

func OfDecimal

func OfDecimal(value int64, scale uint, normalized ...bool) (d Decimal, err error)

OfDecimal creates a Decimal with the given sign, digits, and scale For clarity, there is no default scale

func StringToDecimal

func StringToDecimal(value string) (d Decimal, err error)

StringToDecimal creates a Decimal from the given string The string must contain no more than 18 significant digits, and satisfy the following regex: (-?)([0-9]*)(.[0-9]*)?

func (Decimal) Add

func (d Decimal) Add(o Decimal) (Decimal, error)

Add adds two decimals together by first adjusting them to the same scale, then adding their values Returns an error if: - Adjusting the scale produces an error - Addition overflows or underflows

See addDecimal

func (Decimal) Cmp

func (d Decimal) Cmp(o Decimal) int

Cmp compares d against o, and returns -1, 0, or 1 depending on whether d < o, d = o, or d > o, respectively.

func (Decimal) Div

func (d Decimal) Div(o Decimal) (Decimal, error)

Div is the general form of division, suitable for any two Decimal values. Integer division is used to generate digits by taking remainders and multiplying them by 10 until they are >= divisor, so that the remainder can then be divided further, generating more digits.

Examples:

1. 5000 / 200 5000 / 200 = 25

2. 500.0 / 200 5000 / 200 = 25 Scale 1 - scale 0 = 1 -> Set scale to 1 Result is 2.5

3. 500.0 / 2.00 5000 / 200 = 25 Scale 1 - scale 2 = -1 -> Multiply by 10^1 Result is 250

4. 500.1 / 2.00 5001 / 200 = 25 r 1 Scale 1 - scale 2 = -1 -> Multiply by 10^1 250 r 10 10 / 200 -> 1000 (10 * 10^2) / 200 = 5 scale 2 = 0.05 Result is 250.05

5. 5001 / 200 5001 / 200 = 25 r 1 1 / 200 -> 1000 (1 * 10^3) / 200 = 5 scale 3 = 0.005 Result is 25 + 0.005 = 25.005

6. 5001 / -200 5001 / -200 = -25 r 1 1 / -200 -> 1000 (1 * 10^3) / -200 = -5 scale 3 = -0.005 Result is -25 + -0.005 = -25.005

7. -5001 / 200 -5001 / 200 = -25 r -1 -1 / 200 -> -1000 (1 * 10^3) / 200 = -5 scale 3 = -0.005 Result is -25 + -0.005 = -25.005

8. -5001 / -200 -5001 / -200 = 25 r -1 Adjust remainder sign to 1 1 / 200 -> 1000 (1 * 10^3) / 200 = 5 scale 3 = 0.005 Result is 25 + 0.005 = 25.005

9. -500.1 / 200 -5001 / 200 = -25 r -1 Scale 1 - scale 0 = 1 -> -25 scale 1 = -2.5 -1 / 200 -> -1000 (1 * 10^3) / 200 = -5 scale (1 + 3) = -0.0005 Result is -2.5 + -0.0005 = -2.5005

10. 3 / 2 3 / 2 = 1 r 1 1 / 2 = 10 (1 * 10^1) / 2 = 5 scale 1 Result is 1.5

10. 5.123 / 0.021 5123 / 21 = 243 r 20

20 / 21 = 200 (20 * 10^1) / 21 = 9 scale 1 + 0 r 11 = 0.9          r 11
11 / 21 = 110 (11 * 10^1) / 21 = 5 scale 1 + 1 r 5  = 0.05         r 5
 5 / 21 = 50  (5  * 10^1) / 21 = 2 scale 1 + 2 r 8  = 0.002        r 8
 8 / 21 = 80  (8  * 10^1) / 21 = 3 scale 1 + 3 r 17 = 0.000_3      r 17
17 / 21 = 170 (17 * 10^1) / 21 = 8 scale 1 + 4 r 2  = 0.000_08     r 2
 2 / 21 = 200 (2  * 10^2) / 21 = 9 scale 2 + 5 r 11 = 0.000_000_9  r 11

So a repeating decimal sequence of 952380 -> 243.952380952380952 After the final 2, the next digit is a 3, which means rounding down Final result is still 243.952380952380952

11. 5 / 9 = 0.555... By generating a 19th digit of 5, the result rounds to 0.555_555_555_555_555_556

12. 1.03075 / 0.25 103075 / 25 = 4123 Scale 5 - scale 2 = 3 Result is 4.123

13. 1_234_567_890_123_456.78 / 2.5 123_456_789_012_345_678 / 25 = 4_938_271_560_493_827 r 3 Scale 2 - scale 1 = 1 -> 4_938_271_560_493_827 scale 1 = 493_827_156_049_382.7 3 / 25 = 30 (3 * 10^1) / 25 = 1 scale 1 + 1 r 5 = 0.01 r 5 5 / 25 = 50 (5 * 10^1) / 25 = 2 scale 1 + 2 r 0 = 0.002 Result is 493_827_156_049_382.7 + 0.012 = 493_827_156_049_382.712

14. 1_234_567_890_123_456.78 / 0.25 123_456_789_012_345_678 / 25 = 4_938_271_560_493_827 r 3 Scale 2 - scale 2 = scale 0 -> 4_938_271_560_493_827 3 / 25 = 30 (3 * 10^1) / 25 = 1 scale 1 + 0 r 5 = 0.1 r 5 5 / 25 = 50 (5 * 10^1) / 25 = 2 scale 1 + 1 r 0 = 0.02 Result is 4_938_271_560_493_827 + 0.12 = 4_938_271_560_493_827.12

15. 1_234_567_890_123_456.78 / 0.00025 123_456_789_012_345_678 / 25 = 4_938_271_560_493_827 r 3 Scale 2 - scale 5 = -3 -> Multiply by 10^3 4_938_271_560_493_827_000 = 19 digits = overflow

16. 1 / 100_000_000_000_000_000 1 / 100_000_000_000_000_000 = 100_000_000_000_000_000 (1 * 10^17) / 100_000_000_000_000_000 = 1 scale 17 = 0.000_000_000_000_000_01

17. 1 / 200_000_000_000_000_000 1 / 200_000_000_000_000_000 = 1 * 10^18 / 200_000_000_000_000_000, 1 * 10^18 is too large to store = overflow

18. 100_000_000_000_000_000 / 0.1 = 100_000_000_000_000_000 / 1 = 100_000_000_000_000_000 Scale 0 - 1 = -1 = Multiply by 10^1 = 1 * 10^18 = overflow

func (Decimal) DivIntAdd

func (d Decimal) DivIntAdd(o uint) ([]Decimal, error)

DintIntAdd is like DivIntQuoRem, except that it returns a slice of values that add up to d. EG, 100.00 / 3 = [33.34, 33.33, 33.33]. This method just calls DivIntQuoRem and spreads the remainder across the first remainder values returned.

func (Decimal) DivIntQuoRem

func (d Decimal) DivIntQuoRem(o uint) (Decimal, Decimal, error)

DivIntQuoRem divides d by unsigned integer o, and returns (quotient, remainder, error). The scale of the quotient and remainder are the same as that of d. EG, 100.00 / 3 = 33.33 remainder 0.01.

The divisor o cannot be larger than the dividend d.

Returns a division by zero error if o is zero. Returns a divisor too large error if the o > d.value.

func (Decimal) MagnitudeLessThanOne

func (d Decimal) MagnitudeLessThanOne() bool

MagnitudeLessThanOne returns true if the decimal value represents a value whose mangitude < 1

func (Decimal) Mul

func (d Decimal) Mul(o Decimal) (Decimal, error)

Mul calculates d * o using one of two methods:

1. r = d * o is tried first If r = 0, then return 0 scale 0. If r / d = o, then if r > max value or < min value, we have a valid result 19 digits in length.

Round it to 18 with single divide by 10, and add 1 if remainder >= 5.
Given max int64 value starts with 92, divide by 10 cannot be max value.

Otherwise, go to method 2 below.

The resulting scale rs is d scale + o scale. If rs <= 18, just return r with scale rs. Otherwise, round r (rs - 18) times. If the result is 0, return 0 scale 0, else return r scale rs.

2. If r / d != o, we have a case where d * o exceeds bounds of 64 bit integers. Split d and o into 32-bit upper/lower pairs, and perform a series of shift and adds that generate a 128-bit result.

The 128 bit result is first rounded down to 18 digits, reducing rs by up to 18. If rs = 0 and there are more than 18 digitds l The result rs must be <= 18, return as is.

func (Decimal) MustAdd

func (d Decimal) MustAdd(o Decimal) Decimal

MustAdd is a must version of Add

func (Decimal) MustDiv

func (d Decimal) MustDiv(o Decimal) Decimal

MustDiv is a must version of Div

func (Decimal) MustDivIntAdd

func (d Decimal) MustDivIntAdd(o uint) []Decimal

MustDivIntAdd is a must version of DivIntAdd

func (Decimal) MustDivIntQuoRem

func (d Decimal) MustDivIntQuoRem(o uint) (Decimal, Decimal)

MustDivIntQuoRem is a must version of DivIntQuoRem

func (Decimal) MustMul

func (d Decimal) MustMul(o Decimal) Decimal

MustMul is a must version of Mul

func (Decimal) MustSub

func (d Decimal) MustSub(o Decimal) Decimal

MustSub is a must version of Sub

func (Decimal) Negate

func (d Decimal) Negate() Decimal

Negate returns the negation of d. If 0 is passed, the result is 0.

func (*Decimal) Normalize

func (d *Decimal) Normalize()

Normalize has two cases: value = 0: ensure scale = 0 scale > 0: eliminate useless trailing zeros This can help improve accuracy over successive calculations. This method is the only method that ignores the internal normalize field, to allow forcing normalization as desired.

func (Decimal) Normalized

func (d Decimal) Normalized() bool

Normalized returns true if the operations return normalized values

func (Decimal) Precision

func (d Decimal) Precision() int

Precison returns the total number of digits of a decimal, including trailing zeros. Effectively, the length of the decimal as a string, without a minus sign or decimal point.

func (Decimal) Scale

func (d Decimal) Scale() uint

Scale returns the number of digits after the decimal, if any.

func (Decimal) Sign

func (d Decimal) Sign() (sgn int)

Sign returns the sign of the number: -1 if value < 0

0 if value = 0

+1 if value > 0

func (Decimal) String

func (d Decimal) String() (str string)

String is the Stringer interface

func (Decimal) Sub

func (d Decimal) Sub(o Decimal) (Decimal, error)

Sub subtracts o from d by first adjusting them to the same scale, then subtracting their values Returns an error if: - Adjusting the scale produces an error - Subtraction overflows or underflows

See addDecimal

type Range

type Range[T constraint.IntegerAndFloat] struct {
	// contains filtered or unexported fields
}

Range represents a range of values. The range may be open, half open, or closed.

func OfRange

func OfRange[T constraint.IntegerAndFloat](
	min T,
	minMode RangeMode,
	max T,
	maxMode RangeMode,
	initial T,
) Range[T]

OfRange constructs a range from minimum value and mode, maximum value and mode, and initial value. An initial value is required since min and max could both be open and the type could a float, so there is no sensible default initial value.

Panics if the initial value is not in the specified range.

func (Range[T]) GetMax

func (r Range[T]) GetMax() (T, RangeMode)

GetMax returns the maximum value and mode

func (Range[T]) GetMin

func (r Range[T]) GetMin() (T, RangeMode)

GetMin returns the minimum value and mode

func (Range[T]) GetValue

func (r Range[T]) GetValue() T

GetValue returns the current value

func (*Range[T]) SetValue

func (r *Range[T]) SetValue(val T) error

SetValue sets the value.

Returns an error if the value cannot be set because it is outside the defined bounds, otherwise returns nil

type RangeMode

type RangeMode bool

RangeMode indicates if a minimum or maximum value in a range is open or closed

const (
	Open   RangeMode = false
	Closed RangeMode = true
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL