math: update documentation (#14457)

David 'Epper' Marshall 2022-05-20 01:45:54 -04:00 committed by Jef Roosens
parent b8a0315574
commit 801a88ad16
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
12 changed files with 108 additions and 51 deletions

View File

@ -96,6 +96,7 @@ pub fn exp2(x f64) f64 {
return expmulti(hi, lo, k) return expmulti(hi, lo, k)
} }
// ldexp calculates frac*(2**exp)
pub fn ldexp(frac f64, exp int) f64 { pub fn ldexp(frac f64, exp int) f64 {
return scalbn(frac, exp) return scalbn(frac, exp)
} }
@ -146,6 +147,7 @@ pub fn frexp(x f64) (f64, int) {
return f64_from_bits(y), e_ return f64_from_bits(y), e_
} }
// expm1 calculates e**x - 1
// special cases are: // special cases are:
// expm1(+inf) = +inf // expm1(+inf) = +inf
// expm1(-inf) = -1 // expm1(-inf) = -1
@ -176,7 +178,6 @@ pub fn expm1(x f64) f64 {
} }
} }
// exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2.
fn expmulti(hi f64, lo f64, k int) f64 { fn expmulti(hi f64, lo f64, k int) f64 {
exp_p1 := 1.66666666666666657415e-01 // 0x3FC55555; 0x55555555 exp_p1 := 1.66666666666666657415e-01 // 0x3FC55555; 0x55555555
exp_p2 := -2.77777777770155933842e-03 // 0xBF66C16C; 0x16BEBD93 exp_p2 := -2.77777777770155933842e-03 // 0xBF66C16C; 0x16BEBD93

View File

@ -1,5 +1,6 @@
module math module math
// hypot returns the hypotenuse of the triangle give two sides
pub fn hypot(x f64, y f64) f64 { pub fn hypot(x f64, y f64) f64 {
if is_inf(x, 0) || is_inf(y, 0) { if is_inf(x, 0) || is_inf(y, 0) {
return inf(1) return inf(1)

View File

@ -1,6 +1,7 @@
module math module math
import math.internal import math.internal
// acosh returns the non negative area hyperbolic cosine of x
pub fn acosh(x f64) f64 { pub fn acosh(x f64) f64 {
if x == 0.0 { if x == 0.0 {
@ -19,6 +20,7 @@ pub fn acosh(x f64) f64 {
} }
} }
// asinh returns the area hyperbolic sine of x
pub fn asinh(x f64) f64 { pub fn asinh(x f64) f64 {
a := abs(x) a := abs(x)
s := if x < 0 { -1.0 } else { 1.0 } s := if x < 0 { -1.0 } else { 1.0 }
@ -34,6 +36,7 @@ pub fn asinh(x f64) f64 {
} }
} }
// atanh returns the area hyperbolic tangent of x
pub fn atanh(x f64) f64 { pub fn atanh(x f64) f64 {
a := abs(x) a := abs(x)
s := if x < 0 { -1.0 } else { 1.0 } s := if x < 0 { -1.0 } else { 1.0 }

View File

@ -1,5 +1,6 @@
module math module math
// log_n returns log base b of x
pub fn log_n(x f64, b f64) f64 { pub fn log_n(x f64, b f64) f64 {
y := log(x) y := log(x)
z := log(b) z := log(b)
@ -24,6 +25,7 @@ pub fn log2(x f64) f64 {
return log(frac) * (1.0 / ln2) + f64(exp) return log(frac) * (1.0 / ln2) + f64(exp)
} }
// log1p returns log(1+x)
pub fn log1p(x f64) f64 { pub fn log1p(x f64) f64 {
y := 1.0 + x y := 1.0 + x
z := y - 1.0 z := y - 1.0

View File

@ -155,6 +155,7 @@ pub fn signbit(x f64) bool {
return f64_bits(x) & sign_mask != 0 return f64_bits(x) & sign_mask != 0
} }
// tolerance checks if a and b difference are less than or equal to the tolerance value
pub fn tolerance(a f64, b f64, tol f64) bool { pub fn tolerance(a f64, b f64, tol f64) bool {
mut ee := tol mut ee := tol
// Multiplying by ee here can underflow denormal values to zero. // Multiplying by ee here can underflow denormal values to zero.
@ -178,14 +179,17 @@ pub fn tolerance(a f64, b f64, tol f64) bool {
return d < ee return d < ee
} }
// close checks if a and b are within 1e-14 of each other
pub fn close(a f64, b f64) bool { pub fn close(a f64, b f64) bool {
return tolerance(a, b, 1e-14) return tolerance(a, b, 1e-14)
} }
// veryclose checks if a and b are within 4e-16 of each other
pub fn veryclose(a f64, b f64) bool { pub fn veryclose(a f64, b f64) bool {
return tolerance(a, b, 4e-16) return tolerance(a, b, 4e-16)
} }
// alike checks if a and b are equal
pub fn alike(a f64, b f64) bool { pub fn alike(a f64, b f64) bool {
if is_nan(a) && is_nan(b) { if is_nan(a) && is_nan(b) {
return true return true

View File

@ -4,13 +4,13 @@ fn C.cosf(x f32) f32
fn C.sinf(x f32) f32 fn C.sinf(x f32) f32
// cosf calculates cosine. (float32) // cosf calculates cosine in radians (float32)
[inline] [inline]
pub fn cosf(a f32) f32 { pub fn cosf(a f32) f32 {
return C.cosf(a) return C.cosf(a)
} }
// sinf calculates sine. (float32) // sinf calculates sine in radians (float32)
[inline] [inline]
pub fn sinf(a f32) f32 { pub fn sinf(a f32) f32 {
return C.sinf(a) return C.sinf(a)

View File

@ -4,13 +4,13 @@ fn JS.Math.cos(x f64) f64
fn JS.Math.sin(x f64) f64 fn JS.Math.sin(x f64) f64
// cos calculates cosine. // cos calculates cosine in radians
[inline] [inline]
pub fn cos(a f64) f64 { pub fn cos(a f64) f64 {
return JS.Math.cos(a) return JS.Math.cos(a)
} }
// sin calculates sine. // sin calculates sine in radians
[inline] [inline]
pub fn sin(a f64) f64 { pub fn sin(a f64) f64 {
return JS.Math.sin(a) return JS.Math.sin(a)

View File

@ -44,6 +44,7 @@ const (
} }
) )
// sin calculates the sine of the angle in radians
pub fn sin(x f64) f64 { pub fn sin(x f64) f64 {
p1 := 7.85398125648498535156e-1 p1 := 7.85398125648498535156e-1
p2 := 3.77489470793079817668e-8 p2 := 3.77489470793079817668e-8
@ -82,6 +83,7 @@ pub fn sin(x f64) f64 {
} }
} }
// cos calculates the cosine of the angle in radians
pub fn cos(x f64) f64 { pub fn cos(x f64) f64 {
p1 := 7.85398125648498535156e-1 p1 := 7.85398125648498535156e-1
p2 := 3.77489470793079817668e-8 p2 := 3.77489470793079817668e-8
@ -122,18 +124,19 @@ pub fn cos(x f64) f64 {
} }
} }
// cosf calculates cosine. (float32). // cosf calculates cosine in radians (float32).
[inline] [inline]
pub fn cosf(a f32) f32 { pub fn cosf(a f32) f32 {
return f32(cos(a)) return f32(cos(a))
} }
// sinf calculates sine. (float32) // sinf calculates sine in radians (float32)
[inline] [inline]
pub fn sinf(a f32) f32 { pub fn sinf(a f32) f32 {
return f32(sin(a)) return f32(sin(a))
} }
// sincos calculates the sine and cosine of the angle in radians
pub fn sincos(x f64) (f64, f64) { pub fn sincos(x f64) (f64, f64) {
p1 := 7.85398125648498535156e-1 p1 := 7.85398125648498535156e-1
p2 := 3.77489470793079817668e-8 p2 := 3.77489470793079817668e-8

View File

@ -4,13 +4,13 @@ fn JS.Math.cosh(x f64) f64
fn JS.Math.sinh(x f64) f64 fn JS.Math.sinh(x f64) f64
// cosh calculates hyperbolic cosine. // cosh calculates hyperbolic cosine in radians
[inline] [inline]
pub fn cosh(a f64) f64 { pub fn cosh(a f64) f64 {
return JS.Math.cosh(a) return JS.Math.cosh(a)
} }
// sinh calculates hyperbolic sine. // sinh calculates hyperbolic sine in radians
[inline] [inline]
pub fn sinh(a f64) f64 { pub fn sinh(a f64) f64 {
return JS.Math.sinh(a) return JS.Math.sinh(a)

View File

@ -33,7 +33,7 @@ pub fn sinh(x_ f64) f64 {
return temp return temp
} }
// cosh returns the hyperbolic cosine of x. // cosh returns the hyperbolic cosine of x in radians
// //
// special cases are: // special cases are:
// cosh(±0) = 1 // cosh(±0) = 1

View File

@ -2,7 +2,7 @@ module stats
import math import math
// Measure of Occurance // freq calculates the Measure of Occurance
// Frequency of a given number // Frequency of a given number
// Based on // Based on
// https://www.mathsisfun.com/data/frequency-distribution.html // https://www.mathsisfun.com/data/frequency-distribution.html
@ -19,8 +19,8 @@ pub fn freq<T>(data []T, val T) int {
return count return count
} }
// Measure of Central Tendancy // mean calculates the average
// Mean of the given input array // of the given input array, sum(data)/data.len
// Based on // Based on
// https://www.mathsisfun.com/data/central-measures.html // https://www.mathsisfun.com/data/central-measures.html
pub fn mean<T>(data []T) T { pub fn mean<T>(data []T) T {
@ -34,8 +34,8 @@ pub fn mean<T>(data []T) T {
return sum / T(data.len) return sum / T(data.len)
} }
// Measure of Central Tendancy // geometric_mean calculates the central tendency
// Geometric Mean of the given input array // of the given input array, product(data)**1/data.len
// Based on // Based on
// https://www.mathsisfun.com/numbers/geometric-mean.html // https://www.mathsisfun.com/numbers/geometric-mean.html
pub fn geometric_mean<T>(data []T) T { pub fn geometric_mean<T>(data []T) T {
@ -49,8 +49,8 @@ pub fn geometric_mean<T>(data []T) T {
return math.pow(sum, 1.0 / T(data.len)) return math.pow(sum, 1.0 / T(data.len))
} }
// Measure of Central Tendancy // harmonic_mean calculates the reciprocal of the average of reciprocals
// Harmonic Mean of the given input array // of the given input array
// Based on // Based on
// https://www.mathsisfun.com/numbers/harmonic-mean.html // https://www.mathsisfun.com/numbers/harmonic-mean.html
pub fn harmonic_mean<T>(data []T) T { pub fn harmonic_mean<T>(data []T) T {
@ -64,8 +64,7 @@ pub fn harmonic_mean<T>(data []T) T {
return T(data.len) / sum return T(data.len) / sum
} }
// Measure of Central Tendancy // median returns the middlemost value of the given input array ( input array is assumed to be sorted )
// Median of the given input array ( input array is assumed to be sorted )
// Based on // Based on
// https://www.mathsisfun.com/data/central-measures.html // https://www.mathsisfun.com/data/central-measures.html
pub fn median<T>(sorted_data []T) T { pub fn median<T>(sorted_data []T) T {
@ -80,8 +79,7 @@ pub fn median<T>(sorted_data []T) T {
} }
} }
// Measure of Central Tendancy // mode calculates the highest occuring value of the given input array
// Mode of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/central-measures.html // https://www.mathsisfun.com/data/central-measures.html
pub fn mode<T>(data []T) T { pub fn mode<T>(data []T) T {
@ -101,7 +99,7 @@ pub fn mode<T>(data []T) T {
return data[max] return data[max]
} }
// Root Mean Square of the given input array // rms, Root Mean Square, calculates the sqrt of the mean of the squares of the given input array
// Based on // Based on
// https://en.wikipedia.org/wiki/Root_mean_square // https://en.wikipedia.org/wiki/Root_mean_square
pub fn rms<T>(data []T) T { pub fn rms<T>(data []T) T {
@ -115,8 +113,8 @@ pub fn rms<T>(data []T) T {
return math.sqrt(sum / T(data.len)) return math.sqrt(sum / T(data.len))
} }
// Measure of Dispersion / Spread // population_variance is the Measure of Dispersion / Spread
// Population Variance of the given input array // of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/standard-deviation.html // https://www.mathsisfun.com/data/standard-deviation.html
[inline] [inline]
@ -128,8 +126,8 @@ pub fn population_variance<T>(data []T) T {
return population_variance_mean<T>(data, data_mean) return population_variance_mean<T>(data, data_mean)
} }
// Measure of Dispersion / Spread // population_variance_mean is the Measure of Dispersion / Spread
// Population Variance of the given input array // of the given input array, with the provided mean
// Based on // Based on
// https://www.mathsisfun.com/data/standard-deviation.html // https://www.mathsisfun.com/data/standard-deviation.html
pub fn population_variance_mean<T>(data []T, mean T) T { pub fn population_variance_mean<T>(data []T, mean T) T {
@ -143,8 +141,7 @@ pub fn population_variance_mean<T>(data []T, mean T) T {
return sum / T(data.len) return sum / T(data.len)
} }
// Measure of Dispersion / Spread // sample_variance calculates the spread of dataset around the mean
// Sample Variance of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/standard-deviation.html // https://www.mathsisfun.com/data/standard-deviation.html
[inline] [inline]
@ -156,8 +153,7 @@ pub fn sample_variance<T>(data []T) T {
return sample_variance_mean<T>(data, data_mean) return sample_variance_mean<T>(data, data_mean)
} }
// Measure of Dispersion / Spread // sample_variance calculates the spread of dataset around the provided mean
// Sample Variance of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/standard-deviation.html // https://www.mathsisfun.com/data/standard-deviation.html
pub fn sample_variance_mean<T>(data []T, mean T) T { pub fn sample_variance_mean<T>(data []T, mean T) T {
@ -171,8 +167,7 @@ pub fn sample_variance_mean<T>(data []T, mean T) T {
return sum / T(data.len - 1) return sum / T(data.len - 1)
} }
// Measure of Dispersion / Spread // population_stddev calculates how spread out the dataset is
// Population Standard Deviation of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/standard-deviation.html // https://www.mathsisfun.com/data/standard-deviation.html
[inline] [inline]
@ -183,8 +178,7 @@ pub fn population_stddev<T>(data []T) T {
return math.sqrt(population_variance<T>(data)) return math.sqrt(population_variance<T>(data))
} }
// Measure of Dispersion / Spread // population_stddev_mean calculates how spread out the dataset is, with the provide mean
// Population Standard Deviation of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/standard-deviation.html // https://www.mathsisfun.com/data/standard-deviation.html
[inline] [inline]
@ -219,8 +213,7 @@ pub fn sample_stddev_mean<T>(data []T, mean T) T {
return T(math.sqrt(f64(sample_variance_mean<T>(data, mean)))) return T(math.sqrt(f64(sample_variance_mean<T>(data, mean))))
} }
// Measure of Dispersion / Spread // absdev calculates the average distance between each data point and the mean
// Mean Absolute Deviation of the given input array
// Based on // Based on
// https://en.wikipedia.org/wiki/Average_absolute_deviation // https://en.wikipedia.org/wiki/Average_absolute_deviation
[inline] [inline]
@ -232,8 +225,7 @@ pub fn absdev<T>(data []T) T {
return absdev_mean<T>(data, data_mean) return absdev_mean<T>(data, data_mean)
} }
// Measure of Dispersion / Spread // absdev_mean calculates the average distance between each data point and the provided mean
// Mean Absolute Deviation of the given input array
// Based on // Based on
// https://en.wikipedia.org/wiki/Average_absolute_deviation // https://en.wikipedia.org/wiki/Average_absolute_deviation
pub fn absdev_mean<T>(data []T, mean T) T { pub fn absdev_mean<T>(data []T, mean T) T {
@ -247,7 +239,7 @@ pub fn absdev_mean<T>(data []T, mean T) T {
return sum / T(data.len) return sum / T(data.len)
} }
// Sum of squares // tts, Sum of squares, calculates the sum over all squared differences between values and overall mean
[inline] [inline]
pub fn tss<T>(data []T) T { pub fn tss<T>(data []T) T {
if data.len == 0 { if data.len == 0 {
@ -257,7 +249,7 @@ pub fn tss<T>(data []T) T {
return tss_mean<T>(data, data_mean) return tss_mean<T>(data, data_mean)
} }
// Sum of squares about the mean // tts_mean, Sum of squares, calculates the sum over all squared differences between values and the provided mean
pub fn tss_mean<T>(data []T, mean T) T { pub fn tss_mean<T>(data []T, mean T) T {
if data.len == 0 { if data.len == 0 {
return T(0) return T(0)
@ -269,7 +261,7 @@ pub fn tss_mean<T>(data []T, mean T) T {
return tss return tss
} }
// Minimum of the given input array // min finds the minimum value from the dataset
pub fn min<T>(data []T) T { pub fn min<T>(data []T) T {
if data.len == 0 { if data.len == 0 {
return T(0) return T(0)
@ -283,7 +275,7 @@ pub fn min<T>(data []T) T {
return min return min
} }
// Maximum of the given input array // max finds the maximum value from the dataset
pub fn max<T>(data []T) T { pub fn max<T>(data []T) T {
if data.len == 0 { if data.len == 0 {
return T(0) return T(0)
@ -297,7 +289,7 @@ pub fn max<T>(data []T) T {
return max return max
} }
// Minimum and maximum of the given input array // minmax finds the minimum and maximum value from the dataset
pub fn minmax<T>(data []T) (T, T) { pub fn minmax<T>(data []T) (T, T) {
if data.len == 0 { if data.len == 0 {
return T(0), T(0) return T(0), T(0)
@ -315,7 +307,7 @@ pub fn minmax<T>(data []T) (T, T) {
return min, max return min, max
} }
// Minimum of the given input array // min_index finds the first index of the minimum value
pub fn min_index<T>(data []T) int { pub fn min_index<T>(data []T) int {
if data.len == 0 { if data.len == 0 {
return 0 return 0
@ -331,7 +323,7 @@ pub fn min_index<T>(data []T) int {
return min_index return min_index
} }
// Maximum of the given input array // max_index finds the first index of the maximum value
pub fn max_index<T>(data []T) int { pub fn max_index<T>(data []T) int {
if data.len == 0 { if data.len == 0 {
return 0 return 0
@ -347,7 +339,7 @@ pub fn max_index<T>(data []T) int {
return max_index return max_index
} }
// Minimum and maximum of the given input array // minmax_index finds the first index of the minimum and maximum value
pub fn minmax_index<T>(data []T) (int, int) { pub fn minmax_index<T>(data []T) (int, int) {
if data.len == 0 { if data.len == 0 {
return 0, 0 return 0, 0
@ -369,7 +361,7 @@ pub fn minmax_index<T>(data []T) (int, int) {
return min_index, max_index return min_index, max_index
} }
// Measure of Dispersion / Spread // range calculates the difference between the min and max
// Range ( Maximum - Minimum ) of the given input array // Range ( Maximum - Minimum ) of the given input array
// Based on // Based on
// https://www.mathsisfun.com/data/range.html // https://www.mathsisfun.com/data/range.html
@ -381,6 +373,8 @@ pub fn range<T>(data []T) T {
return max - min return max - min
} }
// covariance calculates directional association between datasets
// positive value denotes variables move in same direction and negative denotes variables move in opposite directions
[inline] [inline]
pub fn covariance<T>(data1 []T, data2 []T) T { pub fn covariance<T>(data1 []T, data2 []T) T {
mean1 := mean<T>(data1) mean1 := mean<T>(data1)
@ -388,7 +382,7 @@ pub fn covariance<T>(data1 []T, data2 []T) T {
return covariance_mean<T>(data1, data2, mean1, mean2) return covariance_mean<T>(data1, data2, mean1, mean2)
} }
// Compute the covariance of a dataset using // covariance_mean computes the covariance of a dataset with means provided
// the recurrence relation // the recurrence relation
pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T { pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T {
n := int(math.min(data1.len, data2.len)) n := int(math.min(data1.len, data2.len))
@ -404,13 +398,16 @@ pub fn covariance_mean<T>(data1 []T, data2 []T, mean1 T, mean2 T) T {
return covariance return covariance
} }
// lag1_autocorrelation_mean calculates the correlation between values that are one time period apart
// of a dataset, based on the mean
[inline] [inline]
pub fn lag1_autocorrelation<T>(data []T) T { pub fn lag1_autocorrelation<T>(data []T) T {
data_mean := mean<T>(data) data_mean := mean<T>(data)
return lag1_autocorrelation_mean<T>(data, data_mean) return lag1_autocorrelation_mean<T>(data, data_mean)
} }
// Compute the lag-1 autocorrelation of a dataset using // lag1_autocorrelation_mean calculates the correlation between values that are one time period apart
// of a dataset, using
// the recurrence relation // the recurrence relation
pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T { pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T {
if data.len == 0 { if data.len == 0 {
@ -427,6 +424,7 @@ pub fn lag1_autocorrelation_mean<T>(data []T, mean T) T {
return q / v return q / v
} }
// kurtosis calculates the measure of the 'tailedness' of the data by finding mean and standard of deviation
[inline] [inline]
pub fn kurtosis<T>(data []T) T { pub fn kurtosis<T>(data []T) T {
data_mean := mean<T>(data) data_mean := mean<T>(data)
@ -434,7 +432,7 @@ pub fn kurtosis<T>(data []T) T {
return kurtosis_mean_stddev<T>(data, data_mean, sd) return kurtosis_mean_stddev<T>(data, data_mean, sd)
} }
// Takes a dataset and finds the kurtosis // kurtosis_mean_stddev calculates the measure of the 'tailedness' of the data
// using the fourth moment the deviations, normalized by the sd // using the fourth moment the deviations, normalized by the sd
pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T { pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T {
mut avg := T(0) // find the fourth moment the deviations, normalized by the sd mut avg := T(0) // find the fourth moment the deviations, normalized by the sd
@ -449,6 +447,7 @@ pub fn kurtosis_mean_stddev<T>(data []T, mean T, sd T) T {
return avg - T(3.0) return avg - T(3.0)
} }
// skew calculates the mean and standard of deviation to find the skew from the data
[inline] [inline]
pub fn skew<T>(data []T) T { pub fn skew<T>(data []T) T {
data_mean := mean<T>(data) data_mean := mean<T>(data)
@ -456,6 +455,7 @@ pub fn skew<T>(data []T) T {
return skew_mean_stddev<T>(data, data_mean, sd) return skew_mean_stddev<T>(data, data_mean, sd)
} }
// skew_mean_stddev calculates the skewness of data
pub fn skew_mean_stddev<T>(data []T, mean T, sd T) T { pub fn skew_mean_stddev<T>(data []T, mean T, sd T) T {
mut skew := T(0) // find the sum of the cubed deviations, normalized by the sd. mut skew := T(0) // find the sum of the cubed deviations, normalized by the sd.
/* /*

View File

@ -14,26 +14,32 @@ pub mut:
hi Uint128 = uint128_zero // upper 128 bit half hi Uint128 = uint128_zero // upper 128 bit half
} }
// uint256_from_128 creates a new `unsigned.Uint256` from the given Uint128 value
pub fn uint256_from_128(v Uint128) Uint256 { pub fn uint256_from_128(v Uint128) Uint256 {
return Uint256{v, uint128_zero} return Uint256{v, uint128_zero}
} }
// uint256_from_64 creates a new `unsigned.Uint256` from the given u64 value
pub fn uint256_from_64(v u64) Uint256 { pub fn uint256_from_64(v u64) Uint256 {
return uint256_from_128(uint128_from_64(v)) return uint256_from_128(uint128_from_64(v))
} }
// is_zero checks if specified Uint256 is zero
pub fn (u Uint256) is_zero() bool { pub fn (u Uint256) is_zero() bool {
return u.lo.is_zero() && u.hi.is_zero() return u.lo.is_zero() && u.hi.is_zero()
} }
// equals checks if the two Uint256 values match one another
pub fn (u Uint256) equals(v Uint256) bool { pub fn (u Uint256) equals(v Uint256) bool {
return u.lo.equals(v.lo) && u.hi.equals(v.hi) return u.lo.equals(v.lo) && u.hi.equals(v.hi)
} }
pub fn (u Uint256) euqals_128(v Uint128) bool { // equals_128 checks if the Uint256 value matches the Uint128 value
pub fn (u Uint256) equals_128(v Uint128) bool {
return u.lo.equals(v) && u.hi.is_zero() return u.lo.equals(v) && u.hi.is_zero()
} }
// cmp returns 1 if u is greater than v, -1 if u is less than v, or 0 if equal
pub fn (u Uint256) cmp(v Uint256) int { pub fn (u Uint256) cmp(v Uint256) int {
h := u.hi.cmp(v.hi) h := u.hi.cmp(v.hi)
if h != 0 { if h != 0 {
@ -42,6 +48,7 @@ pub fn (u Uint256) cmp(v Uint256) int {
return u.lo.cmp(v.lo) return u.lo.cmp(v.lo)
} }
// cmp_128 returns 1 if u is greater than v (Uint128), -1 if u is less than v, or 0 if equal
pub fn (u Uint256) cmp_128(v Uint128) int { pub fn (u Uint256) cmp_128(v Uint128) int {
if !u.hi.is_zero() { if !u.hi.is_zero() {
return 1 return 1
@ -49,34 +56,42 @@ pub fn (u Uint256) cmp_128(v Uint128) int {
return u.lo.cmp(v) return u.lo.cmp(v)
} }
// not returns a binary negation of the Uint256 value
pub fn (u Uint256) not() Uint256 { pub fn (u Uint256) not() Uint256 {
return Uint256{u.lo.not(), u.hi.not()} return Uint256{u.lo.not(), u.hi.not()}
} }
// and returns a Uint256 value that is the bitwise and of u and v
pub fn (u Uint256) and(v Uint256) Uint256 { pub fn (u Uint256) and(v Uint256) Uint256 {
return Uint256{u.lo.and(v.lo), u.hi.and(v.hi)} return Uint256{u.lo.and(v.lo), u.hi.and(v.hi)}
} }
// and_128 returns a Uint256 value that is the bitwise and of u and v, which is a Uint128
pub fn (u Uint256) and_128(v Uint128) Uint256 { pub fn (u Uint256) and_128(v Uint128) Uint256 {
return Uint256{u.lo.and(v), uint128_zero} return Uint256{u.lo.and(v), uint128_zero}
} }
// or_ returns a Uint256 value that is the bitwise or of u and v
pub fn (u Uint256) or_(v Uint256) Uint256 { pub fn (u Uint256) or_(v Uint256) Uint256 {
return Uint256{u.lo.or_(v.lo), u.hi.or_(v.hi)} return Uint256{u.lo.or_(v.lo), u.hi.or_(v.hi)}
} }
// or_128 returns a Uint256 value that is the bitwise or of u and v, which is a Uint128
pub fn (u Uint256) or_128(v Uint128) Uint256 { pub fn (u Uint256) or_128(v Uint128) Uint256 {
return Uint256{u.lo.or_(v), u.hi} return Uint256{u.lo.or_(v), u.hi}
} }
// xor returns a Uint256 value that is the bitwise xor of u and v
pub fn (u Uint256) xor(v Uint256) Uint256 { pub fn (u Uint256) xor(v Uint256) Uint256 {
return Uint256{u.lo.xor(v.lo), u.hi.xor(v.hi)} return Uint256{u.lo.xor(v.lo), u.hi.xor(v.hi)}
} }
// xor_128 returns a Uint256 value that is the bitwise xor of u and v, which is a Uint128
pub fn (u Uint256) xor_128(v Uint128) Uint256 { pub fn (u Uint256) xor_128(v Uint128) Uint256 {
return Uint256{u.lo.xor(v), u.hi} return Uint256{u.lo.xor(v), u.hi}
} }
// add_256 - untested
pub fn add_256(x Uint256, y Uint256, carry u64) (Uint256, u64) { pub fn add_256(x Uint256, y Uint256, carry u64) (Uint256, u64) {
mut sum := Uint256{} mut sum := Uint256{}
mut carry_out := u64(0) mut carry_out := u64(0)
@ -85,6 +100,7 @@ pub fn add_256(x Uint256, y Uint256, carry u64) (Uint256, u64) {
return sum, carry_out return sum, carry_out
} }
// sub_256 - untested
pub fn sub_256(x Uint256, y Uint256, borrow u64) (Uint256, u64) { pub fn sub_256(x Uint256, y Uint256, borrow u64) (Uint256, u64) {
mut diff := Uint256{} mut diff := Uint256{}
mut borrow_out := u64(0) mut borrow_out := u64(0)
@ -93,6 +109,7 @@ pub fn sub_256(x Uint256, y Uint256, borrow u64) (Uint256, u64) {
return diff, borrow_out return diff, borrow_out
} }
// mul_256 - untested
pub fn mul_256(x Uint256, y Uint256) (Uint256, Uint256) { pub fn mul_256(x Uint256, y Uint256) (Uint256, Uint256) {
mut hi := Uint256{} mut hi := Uint256{}
mut lo := Uint256{} mut lo := Uint256{}
@ -114,31 +131,37 @@ pub fn mul_256(x Uint256, y Uint256) (Uint256, Uint256) {
return hi, lo return hi, lo
} }
// add returns a Uint256 that is equal to u+v
pub fn (u Uint256) add(v Uint256) Uint256 { pub fn (u Uint256) add(v Uint256) Uint256 {
sum, _ := add_256(u, v, 0) sum, _ := add_256(u, v, 0)
return sum return sum
} }
// overflowing_add - untested
pub fn (u Uint256) overflowing_add(v Uint256) (Uint256, u64) { pub fn (u Uint256) overflowing_add(v Uint256) (Uint256, u64) {
sum, overflow := add_256(u, v, 0) sum, overflow := add_256(u, v, 0)
return sum, overflow return sum, overflow
} }
// add_128 returns a Uint256 that is equal to u+v, v being a Uint128
pub fn (u Uint256) add_128(v Uint128) Uint256 { pub fn (u Uint256) add_128(v Uint128) Uint256 {
lo, c0 := add_128(u.lo, v, 0) lo, c0 := add_128(u.lo, v, 0)
return Uint256{lo, u.hi.add_64(c0)} return Uint256{lo, u.hi.add_64(c0)}
} }
// sub returns a Uint256 that is equal to u-v
pub fn (u Uint256) sub(v Uint256) Uint256 { pub fn (u Uint256) sub(v Uint256) Uint256 {
diff, _ := sub_256(u, v, 0) diff, _ := sub_256(u, v, 0)
return diff return diff
} }
// sub_128 returns a Uint256 that is equal to u-v, v being a Uint128
pub fn (u Uint256) sub_128(v Uint128) Uint256 { pub fn (u Uint256) sub_128(v Uint128) Uint256 {
lo, b0 := sub_128(u.lo, v, 0) lo, b0 := sub_128(u.lo, v, 0)
return Uint256{lo, u.hi.sub_64(b0)} return Uint256{lo, u.hi.sub_64(b0)}
} }
// mul returns a Uint256 that is eqal to u*v
pub fn (u Uint256) mul(v Uint256) Uint256 { pub fn (u Uint256) mul(v Uint256) Uint256 {
mut hi, mut lo := mul_128(u.lo, v.lo) mut hi, mut lo := mul_128(u.lo, v.lo)
hi = hi.add(u.hi.mul(v.lo)) hi = hi.add(u.hi.mul(v.lo))
@ -146,11 +169,13 @@ pub fn (u Uint256) mul(v Uint256) Uint256 {
return Uint256{lo, hi} return Uint256{lo, hi}
} }
// mul_128 returns a Uint256 that is eqal to u*v, v being a Uint128
pub fn (u Uint256) mul_128(v Uint128) Uint256 { pub fn (u Uint256) mul_128(v Uint128) Uint256 {
hi, lo := mul_128(u.lo, v) hi, lo := mul_128(u.lo, v)
return Uint256{lo, hi.add(u.hi.mul(v))} return Uint256{lo, hi.add(u.hi.mul(v))}
} }
// quo_rem - untested
pub fn (u Uint256) quo_rem(v Uint256) (Uint256, Uint256) { pub fn (u Uint256) quo_rem(v Uint256) (Uint256, Uint256) {
if v.hi.is_zero() { if v.hi.is_zero() {
q, r := u.quo_rem_128(v.lo) q, r := u.quo_rem_128(v.lo)
@ -173,6 +198,7 @@ pub fn (u Uint256) quo_rem(v Uint256) (Uint256, Uint256) {
return q, r return q, r
} }
// quo_rem_128 - untested
pub fn (u Uint256) quo_rem_128(v Uint128) (Uint256, Uint128) { pub fn (u Uint256) quo_rem_128(v Uint128) (Uint256, Uint128) {
if u.hi.cmp(v) < 0 { if u.hi.cmp(v) < 0 {
lo, r := div_128(u.hi, u.lo, v) lo, r := div_128(u.hi, u.lo, v)
@ -184,6 +210,7 @@ pub fn (u Uint256) quo_rem_128(v Uint128) (Uint256, Uint128) {
return Uint256{lo, hi}, r2 return Uint256{lo, hi}, r2
} }
// quo_rem_64 - untested
pub fn (u Uint256) quo_rem_64(v u64) (Uint256, u64) { pub fn (u Uint256) quo_rem_64(v u64) (Uint256, u64) {
mut q := Uint256{} mut q := Uint256{}
mut r := u64(0) mut r := u64(0)
@ -192,6 +219,7 @@ pub fn (u Uint256) quo_rem_64(v u64) (Uint256, u64) {
return q, r return q, r
} }
// rsh returns a new Uint256 that has been right bit shifted
pub fn (u Uint256) rsh(n_ u32) Uint256 { pub fn (u Uint256) rsh(n_ u32) Uint256 {
mut n := n_ mut n := n_
if n > 128 { if n > 128 {
@ -205,6 +233,7 @@ pub fn (u Uint256) rsh(n_ u32) Uint256 {
return Uint256{Uint128{u.lo.lo >> n | u.lo.hi << (64 - n), u.lo.hi >> n | u.hi.lo << (64 - n)}, Uint128{u.hi.lo >> n | u.hi.hi << (64 - n), u.hi.hi >> n}} return Uint256{Uint128{u.lo.lo >> n | u.lo.hi << (64 - n), u.lo.hi >> n | u.hi.lo << (64 - n)}, Uint128{u.hi.lo >> n | u.hi.hi << (64 - n), u.hi.hi >> n}}
} }
// lsh returns a new Uint256 that has been left bit shifted
pub fn (u Uint256) lsh(n_ u32) Uint256 { pub fn (u Uint256) lsh(n_ u32) Uint256 {
mut n := n_ mut n := n_
if n > 128 { if n > 128 {
@ -219,36 +248,43 @@ pub fn (u Uint256) lsh(n_ u32) Uint256 {
return Uint256{Uint128{u.lo.lo << n, u.lo.hi << n | u.lo.lo >> (64 - n)}, Uint128{u.hi.lo << n | u.lo.hi >> (64 - n), u.hi.hi << n | u.hi.lo >> (64 - n)}} return Uint256{Uint128{u.lo.lo << n, u.lo.hi << n | u.lo.lo >> (64 - n)}, Uint128{u.hi.lo << n | u.lo.hi >> (64 - n), u.hi.hi << n | u.hi.lo >> (64 - n)}}
} }
// div - untested
pub fn (u Uint256) div(v Uint256) Uint256 { pub fn (u Uint256) div(v Uint256) Uint256 {
q, _ := u.quo_rem(v) q, _ := u.quo_rem(v)
return q return q
} }
// div_128 - untested
pub fn (u Uint256) div_128(v Uint128) Uint256 { pub fn (u Uint256) div_128(v Uint128) Uint256 {
q, _ := u.quo_rem_128(v) q, _ := u.quo_rem_128(v)
return q return q
} }
// div_64 - untested
pub fn (u Uint256) div_64(v u64) Uint256 { pub fn (u Uint256) div_64(v u64) Uint256 {
q, _ := u.quo_rem_64(v) q, _ := u.quo_rem_64(v)
return q return q
} }
// mod - untested
pub fn (u Uint256) mod(v Uint256) Uint256 { pub fn (u Uint256) mod(v Uint256) Uint256 {
_, r := u.quo_rem(v) _, r := u.quo_rem(v)
return r return r
} }
// mod_128 - untested
pub fn (u Uint256) mod_128(v Uint128) Uint128 { pub fn (u Uint256) mod_128(v Uint128) Uint128 {
_, r := u.quo_rem_128(v) _, r := u.quo_rem_128(v)
return r return r
} }
// mod_64 - untested
pub fn (u Uint256) mod_64(v u64) u64 { pub fn (u Uint256) mod_64(v u64) u64 {
_, r := u.quo_rem_64(v) _, r := u.quo_rem_64(v)
return r return r
} }
// rotate_left returns a new Uint256 that has been left bit shifted
pub fn (u Uint256) rotate_left(k int) Uint256 { pub fn (u Uint256) rotate_left(k int) Uint256 {
mut n := u32(k) & 255 mut n := u32(k) & 255
if n < 64 { if n < 64 {
@ -283,10 +319,12 @@ pub fn (u Uint256) rotate_left(k int) Uint256 {
return Uint256{Uint128{u.lo.hi << n | u.lo.lo >> (64 - n), u.hi.lo << n | u.lo.hi >> (64 - n)}, Uint128{u.hi.hi << n | u.hi.lo >> (64 - n), u.lo.lo << n | u.hi.hi >> (64 - n)}} return Uint256{Uint128{u.lo.hi << n | u.lo.lo >> (64 - n), u.hi.lo << n | u.lo.hi >> (64 - n)}, Uint128{u.hi.hi << n | u.hi.lo >> (64 - n), u.lo.lo << n | u.hi.hi >> (64 - n)}}
} }
// rotate_right returns a new Uint256 that has been right bit shifted
pub fn (u Uint256) rotate_right(k int) Uint256 { pub fn (u Uint256) rotate_right(k int) Uint256 {
return u.rotate_left(-k) return u.rotate_left(-k)
} }
// len returns the length of the binary value without the leading zeros
pub fn (u Uint256) len() int { pub fn (u Uint256) len() int {
if !u.hi.is_zero() { if !u.hi.is_zero() {
return 128 + u.hi.len() return 128 + u.hi.len()
@ -294,6 +332,7 @@ pub fn (u Uint256) len() int {
return u.lo.len() return u.lo.len()
} }
// leading_zeros returns the number of 0s at the beginning of the binary value of the Uint256 value [0, 256]
pub fn (u Uint256) leading_zeros() int { pub fn (u Uint256) leading_zeros() int {
if !u.hi.is_zero() { if !u.hi.is_zero() {
return u.hi.leading_zeros() return u.hi.leading_zeros()
@ -301,6 +340,7 @@ pub fn (u Uint256) leading_zeros() int {
return 128 + u.lo.leading_zeros() return 128 + u.lo.leading_zeros()
} }
// trailing_zeros returns the number of 0s at the end of the binary value of the Uint256 value [0,256]
pub fn (u Uint256) trailing_zeros() int { pub fn (u Uint256) trailing_zeros() int {
if !u.lo.is_zero() { if !u.lo.is_zero() {
return u.lo.trailing_zeros() return u.lo.trailing_zeros()
@ -309,10 +349,12 @@ pub fn (u Uint256) trailing_zeros() int {
return 128 + u.hi.trailing_zeros() return 128 + u.hi.trailing_zeros()
} }
// ones_count returns the number of ones in the binary value of the Uint256 value
pub fn (u Uint256) ones_count() int { pub fn (u Uint256) ones_count() int {
return u.lo.ones_count() + u.hi.ones_count() return u.lo.ones_count() + u.hi.ones_count()
} }
// str returns the decimal representation of the unsigned integer
pub fn (u_ Uint256) str() string { pub fn (u_ Uint256) str() string {
mut u := u_ mut u := u_
if u.hi.is_zero() { if u.hi.is_zero() {
@ -339,6 +381,7 @@ pub fn (u_ Uint256) str() string {
return '' return ''
} }
// uint256_from_dec_str creates a new `unsigned.Uint256` from the given string if possible
pub fn uint256_from_dec_str(value string) ?Uint256 { pub fn uint256_from_dec_str(value string) ?Uint256 {
mut res := unsigned.uint256_zero mut res := unsigned.uint256_zero
for b_ in value.bytes() { for b_ in value.bytes() {