diff options
Diffstat (limited to 'lib/pure/math.nim')
-rw-r--r-- | lib/pure/math.nim | 516 |
1 files changed, 427 insertions, 89 deletions
diff --git a/lib/pure/math.nim b/lib/pure/math.nim index ee32772b1..460be1cd0 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -7,15 +7,48 @@ # distribution, for details about the copyright. # -## Constructive mathematics is naturally typed. -- Simon Thompson +## *Constructive mathematics is naturally typed.* -- Simon Thompson ## ## Basic math routines for Nim. +## +## Note that the trigonometric functions naturally operate on radians. +## The helper functions `degToRad<#degToRad,T>`_ and `radToDeg<#radToDeg,T>`_ +## provide conversion between radians and degrees. +## +## .. code-block:: +## +## import math +## from sequtils import map +## +## let a = [0.0, PI/6, PI/4, PI/3, PI/2] +## +## echo a.map(sin) +## # @[0.0, 0.499…, 0.707…, 0.866…, 1.0] +## +## echo a.map(tan) +## # @[0.0, 0.577…, 0.999…, 1.732…, 1.633…e+16] +## +## echo cos(degToRad(180.0)) +## # -1.0 +## +## echo sqrt(-1.0) +## # nan (use `complex` module) +## ## This module is available for the `JavaScript target ## <backends.html#the-javascript-target>`_. ## -## Note that the trigonometric functions naturally operate on radians. -## The helper functions `degToRad` and `radToDeg` provide conversion -## between radians and degrees. +## **See also:** +## * `complex module<complex.html>`_ for complex numbers and their +## mathematical operations +## * `rationals module<rationals.html>`_ for rational numbers and their +## mathematical operations +## * `fenv module<fenv.html>`_ for handling of floating-point rounding +## and exceptions (overflow, zero-devide, etc.) +## * `random module<random.html>`_ for fast and tiny random number generator +## * `mersenne module<mersenne.html>`_ for Mersenne twister random number generator +## * `stats module<stats.html>`_ for statistical analysis +## * `strformat module<strformat>`_ for formatting floats for print + include "system/inclrtl" {.push debugger:off .} # the user does not want to trace a part @@ -25,9 +58,11 @@ import bitops proc binom*(n, k: int): int {.noSideEffect.} = ## Computes the `binomial coefficient <https://en.wikipedia.org/wiki/Binomial_coefficient>`_. - ## - ## .. code-block:: nim - ## echo binom(6, 2) ## 15 + runnableExamples: + doAssert binom(6, 2) == binom(6, 4) + doAssert binom(6, 2) == 15 + doAssert binom(-6, 2) == 1 + doAssert binom(6, 0) == 1 if k <= 0: return 1 if 2*k > n: return binom(n, n-k) result = n @@ -40,10 +75,15 @@ proc createFactTable[N: static[int]]: array[N, int] = result[i] = result[i - 1] * i proc fac*(n: int): int = - ## Computes the `factorial <https://en.wikipedia.org/wiki/Factorial>`_ of a non-negative integer ``n`` + ## Computes the `factorial <https://en.wikipedia.org/wiki/Factorial>`_ of + ## a non-negative integer ``n``. ## - ## .. code-block:: nim - ## echo fac(4) ## 24 + ## See also: + ## * `prod proc <#prod,openArray[T]>`_ + runnableExamples: + doAssert fac(3) == 6 + doAssert fac(4) == 24 + doAssert fac(10) == 3628800 const factTable = when sizeof(int) == 4: createFactTable[13]() @@ -59,25 +99,26 @@ when defined(Posix): {.passl: "-lm".} const - PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number) - TAU* = 2.0 * PI ## the circle constant TAU (= 2 * PI) + PI* = 3.1415926535897932384626433 ## The circle constant PI (Ludolph's number) + TAU* = 2.0 * PI ## The circle constant TAU (= 2 * PI) E* = 2.71828182845904523536028747 ## Euler's number - MaxFloat64Precision* = 16 ## maximum number of meaningful digits + MaxFloat64Precision* = 16 ## Maximum number of meaningful digits ## after the decimal point for Nim's ## ``float64`` type. - MaxFloat32Precision* = 8 ## maximum number of meaningful digits + MaxFloat32Precision* = 8 ## Maximum number of meaningful digits ## after the decimal point for Nim's ## ``float32`` type. - MaxFloatPrecision* = MaxFloat64Precision ## maximum number of + MaxFloatPrecision* = MaxFloat64Precision ## Maximum number of ## meaningful digits ## after the decimal point ## for Nim's ``float`` type. - RadPerDeg = PI / 180.0 ## number of radians per degree + RadPerDeg = PI / 180.0 ## Number of radians per degree type - FloatClass* = enum ## describes the class a floating point value belongs to. - ## This is the type that is returned by `classify`. + FloatClass* = enum ## Describes the class a floating point value belongs to. + ## This is the type that is returned by + ## `classify proc <#classify,float>`_. fcNormal, ## value is an ordinary nonzero floating point value fcSubnormal, ## value is a subnormal (a very small) floating point value fcZero, ## value is zero @@ -87,13 +128,14 @@ type fcNegInf ## value is negative infinity proc classify*(x: float): FloatClass = - ## Classifies a floating point value. Returns ``x``'s class as specified by - ## `FloatClass`. + ## Classifies a floating point value. ## - ## .. code-block:: nim - ## echo classify(0.3) ## fcNormal - ## echo classify(0.0) ## fcZero - ## echo classify(0.3/0.0) ## fcInf + ## Returns ``x``'s class as specified by `FloatClass enum<#FloatClass>`_. + runnableExamples: + doAssert classify(0.3) == fcNormal + doAssert classify(0.0) == fcZero + doAssert classify(0.3/0.0) == fcInf + doAssert classify(-0.3/0.0) == fcNegInf # JavaScript and most C compilers have no classify: if x == 0.0: @@ -110,20 +152,30 @@ proc classify*(x: float): FloatClass = proc isPowerOfTwo*(x: int): bool {.noSideEffect.} = ## Returns ``true``, if ``x`` is a power of two, ``false`` otherwise. + ## ## Zero and negative numbers are not a power of two. ## - ## .. code-block:: nim - ## echo isPowerOfTwo(5) ## false - ## echo isPowerOfTwo(8) ## true + ## See also: + ## * `nextPowerOfTwo proc<#nextPowerOfTwo,int>`_ + runnableExamples: + doAssert isPowerOfTwo(16) == true + doAssert isPowerOfTwo(5) == false + doAssert isPowerOfTwo(0) == false + doAssert isPowerOfTwo(-16) == false return (x > 0) and ((x and (x - 1)) == 0) proc nextPowerOfTwo*(x: int): int {.noSideEffect.} = ## Returns ``x`` rounded up to the nearest power of two. + ## ## Zero and negative numbers get rounded up to 1. ## - ## .. code-block:: nim - ## echo nextPowerOfTwo(8) ## 8 - ## echo nextPowerOfTwo(9) ## 16 + ## See also: + ## * `isPowerOfTwo proc<#isPowerOfTwo,int>`_ + runnableExamples: + doAssert nextPowerOfTwo(16) == 16 + doAssert nextPowerOfTwo(5) == 8 + doAssert nextPowerOfTwo(0) == 1 + doAssert nextPowerOfTwo(-16) == 1 result = x - 1 when defined(cpu64): result = result or (result shr 32) @@ -138,9 +190,12 @@ proc nextPowerOfTwo*(x: int): int {.noSideEffect.} = proc countBits32*(n: int32): int {.noSideEffect.} = ## Counts the set bits in ``n``. - ## - ## .. code-block:: nim - ## echo countBits32(13'i32) ## 3 + runnableExamples: + doAssert countBits32(7) == 3 + doAssert countBits32(8) == 1 + doAssert countBits32(15) == 4 + doAssert countBits32(16) == 1 + doAssert countBits32(17) == 2 var v = n v = v -% ((v shr 1'i32) and 0x55555555'i32) v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32) @@ -148,41 +203,99 @@ proc countBits32*(n: int32): int {.noSideEffect.} = proc sum*[T](x: openArray[T]): T {.noSideEffect.} = ## Computes the sum of the elements in ``x``. + ## ## If ``x`` is empty, 0 is returned. ## - ## .. code-block:: nim - ## echo sum([1.0, 2.5, -3.0, 4.3]) ## 4.8 + ## See also: + ## * `prod proc <#prod,openArray[T]>`_ + ## * `cumsum proc <#cumsum,openArray[T]>`_ + ## * `cumsummed proc <#cumsummed,openArray[T]>`_ + runnableExamples: + doAssert sum([1, 2, 3, 4]) == 10 + doAssert sum([-1.5, 2.7, -0.1]) == 1.1 for i in items(x): result = result + i proc prod*[T](x: openArray[T]): T {.noSideEffect.} = ## Computes the product of the elements in ``x``. + ## ## If ``x`` is empty, 1 is returned. ## - ## .. code-block:: nim - ## echo prod([1.0, 3.0, -0.2]) ## -0.6 + ## See also: + ## * `sum proc <#sum,openArray[T]>`_ + ## * `fac proc <#fac,int>`_ + runnableExamples: + doAssert prod([1, 2, 3, 4]) == 24 + doAssert prod([-4, 3, 5]) == -60 result = 1.T for i in items(x): result = result * i +proc cumsummed*[T](x: openArray[T]): seq[T] = + ## Return cumulative (aka prefix) summation of ``x``. + ## + ## See also: + ## * `sum proc <#sum,openArray[T]>`_ + ## * `cumsum proc <#cumsum,openArray[T]>`_ for the in-place version + runnableExamples: + let a = [1, 2, 3, 4] + doAssert cumsummed(a) == @[1, 3, 6, 10] + result.setLen(x.len) + result[0] = x[0] + for i in 1 ..< x.len: result[i] = result[i-1] + x[i] + +proc cumsum*[T](x: var openArray[T]) = + ## Transforms ``x`` in-place (must be declared as `var`) into its + ## cumulative (aka prefix) summation. + ## + ## See also: + ## * `sum proc <#sum,openArray[T]>`_ + ## * `cumsummed proc <#cumsummed,openArray[T]>`_ for a version which + ## returns cumsummed sequence + runnableExamples: + var a = [1, 2, 3, 4] + cumsum(a) + doAssert a == @[1, 3, 6, 10] + for i in 1 ..< x.len: x[i] = x[i-1] + x[i] + {.push noSideEffect.} when not defined(JS): # C proc sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".} proc sqrt*(x: float64): float64 {.importc: "sqrt", header: "<math.h>".} ## Computes the square root of ``x``. ## + ## See also: + ## * `cbrt proc <#cbrt,float64>`_ for cubic root + ## ## .. code-block:: nim + ## echo sqrt(4.0) ## 2.0 ## echo sqrt(1.44) ## 1.2 + ## echo sqrt(-4.0) ## nan proc cbrt*(x: float32): float32 {.importc: "cbrtf", header: "<math.h>".} proc cbrt*(x: float64): float64 {.importc: "cbrt", header: "<math.h>".} ## Computes the cubic root of ``x``. ## + ## See also: + ## * `sqrt proc <#sqrt,float64>`_ for square root + ## ## .. code-block:: nim + ## echo cbrt(8.0) ## 2.0 ## echo cbrt(2.197) ## 1.3 + ## echo cbrt(-27.0) ## -3.0 proc ln*(x: float32): float32 {.importc: "logf", header: "<math.h>".} proc ln*(x: float64): float64 {.importc: "log", header: "<math.h>".} - ## Computes the `natural logarithm <https://en.wikipedia.org/wiki/Natural_logarithm>`_ of ``x``. + ## Computes the `natural logarithm <https://en.wikipedia.org/wiki/Natural_logarithm>`_ + ## of ``x``. + ## + ## See also: + ## * `log proc <#log,T,T>`_ + ## * `log10 proc <#log10,float64>`_ + ## * `log2 proc <#log2,float64>`_ + ## * `exp proc <#exp,float64>`_ ## ## .. code-block:: nim ## echo ln(exp(4.0)) ## 4.0 + ## echo ln(1.0)) ## 0.0 + ## echo ln(0.0) ## -inf + ## echo ln(-7.0) ## nan else: # JS proc sqrt*(x: float32): float32 {.importc: "Math.sqrt", nodecl.} proc sqrt*(x: float64): float64 {.importc: "Math.sqrt", nodecl.} @@ -193,8 +306,18 @@ else: # JS proc log*[T: SomeFloat](x, base: T): T = ## Computes the logarithm of ``x`` to base ``base``. ## + ## See also: + ## * `ln proc <#ln,float64>`_ + ## * `log10 proc <#log10,float64>`_ + ## * `log2 proc <#log2,float64>`_ + ## * `exp proc <#exp,float64>`_ + ## ## .. code-block:: nim - ## echo log(9.0, 3.0) ## 2.0 + ## echo log(9.0, 3.0) ## 2.0 + ## echo log(32.0, 2.0) ## 5.0 + ## echo log(0.0, 2.0) ## -inf + ## echo log(-7.0, 4.0) ## nan + ## echo log(8.0, -2.0) ## nan ln(x) / ln(base) when not defined(JS): # C @@ -202,77 +325,164 @@ when not defined(JS): # C proc log10*(x: float64): float64 {.importc: "log10", header: "<math.h>".} ## Computes the common logarithm (base 10) of ``x``. ## + ## See also: + ## * `ln proc <#ln,float64>`_ + ## * `log proc <#log,T,T>`_ + ## * `log2 proc <#log2,float64>`_ + ## * `exp proc <#exp,float64>`_ + ## ## .. code-block:: nim - ## echo log10(100.0) ## 2.0 + ## echo log10(100.0) ## 2.0 + ## echo log10(0.0) ## nan + ## echo log10(-100.0) ## -inf proc exp*(x: float32): float32 {.importc: "expf", header: "<math.h>".} proc exp*(x: float64): float64 {.importc: "exp", header: "<math.h>".} - ## Computes the exponential function of ``x`` (pow(E, x)). + ## Computes the exponential function of ``x`` (e^x). + ## + ## See also: + ## * `ln proc <#ln,float64>`_ + ## * `log proc <#log,T,T>`_ + ## * `log10 proc <#log10,float64>`_ + ## * `log2 proc <#log2,float64>`_ ## ## .. code-block:: nim - ## echo exp(1.0) ## 2.718281828459045 + ## echo exp(1.0) ## 2.718281828459045 ## echo ln(exp(4.0)) ## 4.0 + ## echo exp(0.0) ## 1.0 + ## echo exp(-1.0) ## 0.3678794411714423 proc sin*(x: float32): float32 {.importc: "sinf", header: "<math.h>".} proc sin*(x: float64): float64 {.importc: "sin", header: "<math.h>".} ## Computes the sine of ``x``. ## + ## See also: + ## * `cos proc <#cos,float64>`_ + ## * `tan proc <#tan,float64>`_ + ## * `arcsin proc <#arcsin,float64>`_ + ## * `sinh proc <#sinh,float64>`_ + ## ## .. code-block:: nim - ## echo sin(PI / 6) ## 0.4999999999999999 + ## echo sin(PI / 6) ## 0.4999999999999999 ## echo sin(degToRad(90.0)) ## 1.0 proc cos*(x: float32): float32 {.importc: "cosf", header: "<math.h>".} proc cos*(x: float64): float64 {.importc: "cos", header: "<math.h>".} ## Computes the cosine of ``x``. ## + ## See also: + ## * `sin proc <#sin,float64>`_ + ## * `tan proc <#tan,float64>`_ + ## * `arccos proc <#arccos,float64>`_ + ## * `cosh proc <#cosh,float64>`_ + ## ## .. code-block:: nim - ## echo cos(2 * PI) ## 1.0 + ## echo cos(2 * PI) ## 1.0 ## echo cos(degToRad(60.0)) ## 0.5000000000000001 proc tan*(x: float32): float32 {.importc: "tanf", header: "<math.h>".} proc tan*(x: float64): float64 {.importc: "tan", header: "<math.h>".} ## Computes the tangent of ``x``. ## + ## See also: + ## * `sin proc <#sin,float64>`_ + ## * `cos proc <#cos,float64>`_ + ## * `arctan proc <#arctan,float64>`_ + ## * `tanh proc <#tanh,float64>`_ + ## ## .. code-block:: nim ## echo tan(degToRad(45.0)) ## 0.9999999999999999 - ## echo tan(PI / 4) ## 0.9999999999999999 + ## echo tan(PI / 4) ## 0.9999999999999999 proc sinh*(x: float32): float32 {.importc: "sinhf", header: "<math.h>".} proc sinh*(x: float64): float64 {.importc: "sinh", header: "<math.h>".} ## Computes the `hyperbolic sine <https://en.wikipedia.org/wiki/Hyperbolic_function#Definitions>`_ of ``x``. ## + ## See also: + ## * `cosh proc <#cosh,float64>`_ + ## * `tanh proc <#tanh,float64>`_ + ## * `arcsinh proc <#arcsinh,float64>`_ + ## * `sin proc <#sin,float64>`_ + ## ## .. code-block:: nim - ## echo sinh(1.0) ## 1.175201193643801 + ## echo sinh(0.0) ## 0.0 + ## echo sinh(1.0) ## 1.175201193643801 + ## echo sinh(degToRad(90.0)) ## 2.301298902307295 proc cosh*(x: float32): float32 {.importc: "coshf", header: "<math.h>".} proc cosh*(x: float64): float64 {.importc: "cosh", header: "<math.h>".} ## Computes the `hyperbolic cosine <https://en.wikipedia.org/wiki/Hyperbolic_function#Definitions>`_ of ``x``. ## + ## See also: + ## * `sinh proc <#sinh,float64>`_ + ## * `tanh proc <#tanh,float64>`_ + ## * `arccosh proc <#arccosh,float64>`_ + ## * `cos proc <#cos,float64>`_ + ## ## .. code-block:: nim - ## echo cosh(1.0) ## 1.543080634815244 + ## echo cosh(0.0) ## 1.0 + ## echo cosh(1.0) ## 1.543080634815244 + ## echo cosh(degToRad(90.0)) ## 2.509178478658057 proc tanh*(x: float32): float32 {.importc: "tanhf", header: "<math.h>".} proc tanh*(x: float64): float64 {.importc: "tanh", header: "<math.h>".} ## Computes the `hyperbolic tangent <https://en.wikipedia.org/wiki/Hyperbolic_function#Definitions>`_ of ``x``. ## + ## See also: + ## * `sinh proc <#sinh,float64>`_ + ## * `cosh proc <#cosh,float64>`_ + ## * `arctanh proc <#arctanh,float64>`_ + ## * `tan proc <#tan,float64>`_ + ## ## .. code-block:: nim - ## echo tanh(1.0) ## 0.7615941559557649 + ## echo tanh(0.0) ## 0.0 + ## echo tanh(1.0) ## 0.7615941559557649 + ## echo tanh(degToRad(90.0)) ## 0.9171523356672744 proc arccos*(x: float32): float32 {.importc: "acosf", header: "<math.h>".} proc arccos*(x: float64): float64 {.importc: "acos", header: "<math.h>".} ## Computes the arc cosine of ``x``. ## + ## See also: + ## * `arcsin proc <#arcsin,float64>`_ + ## * `arctan proc <#arctan,float64>`_ + ## * `arctan2 proc <#arctan2,float64,float64>`_ + ## * `cos proc <#cos,float64>`_ + ## ## .. code-block:: nim - ## echo arccos(1.0) ## 0.0 + ## echo radToDeg(arccos(0.0)) ## 90.0 + ## echo radToDeg(arccos(1.0)) ## 0.0 proc arcsin*(x: float32): float32 {.importc: "asinf", header: "<math.h>".} proc arcsin*(x: float64): float64 {.importc: "asin", header: "<math.h>".} ## Computes the arc sine of ``x``. + ## + ## See also: + ## * `arccos proc <#arccos,float64>`_ + ## * `arctan proc <#arctan,float64>`_ + ## * `arctan2 proc <#arctan2,float64,float64>`_ + ## * `sin proc <#sin,float64>`_ + ## + ## .. code-block:: nim + ## echo radToDeg(arcsin(0.0)) ## 0.0 + ## echo radToDeg(arcsin(1.0)) ## 90.0 proc arctan*(x: float32): float32 {.importc: "atanf", header: "<math.h>".} proc arctan*(x: float64): float64 {.importc: "atan", header: "<math.h>".} ## Calculate the arc tangent of ``x``. ## + ## See also: + ## * `arcsin proc <#arcsin,float64>`_ + ## * `arccos proc <#arccos,float64>`_ + ## * `arctan2 proc <#arctan2,float64,float64>`_ + ## * `tan proc <#tan,float64>`_ + ## ## .. code-block:: nim ## echo arctan(1.0) ## 0.7853981633974483 ## echo radToDeg(arctan(1.0)) ## 45.0 proc arctan2*(y, x: float32): float32 {.importc: "atan2f", header: "<math.h>".} proc arctan2*(y, x: float64): float64 {.importc: "atan2", header: "<math.h>".} ## Calculate the arc tangent of ``y`` / ``x``. - ## `arctan2` returns the arc tangent of ``y`` / ``x``; it produces correct - ## results even when the resulting angle is near pi/2 or -pi/2 - ## (``x`` near 0). + ## + ## It produces correct results even when the resulting angle is near + ## pi/2 or -pi/2 (``x`` near 0). + ## + ## See also: + ## * `arcsin proc <#arcsin,float64>`_ + ## * `arccos proc <#arccos,float64>`_ + ## * `arctan proc <#arctan,float64>`_ + ## * `tan proc <#tan,float64>`_ ## ## .. code-block:: nim ## echo arctan2(1.0, 0.0) ## 1.570796326794897 @@ -313,18 +523,18 @@ else: # JS proc arctanh*[T: float32|float64](x: T): T {.importc: "Math.atanh", nodecl.} proc cot*[T: float32|float64](x: T): T = 1.0 / tan(x) - ## Computes the cotangent of ``x``. + ## Computes the cotangent of ``x`` (1 / tan(x)). proc sec*[T: float32|float64](x: T): T = 1.0 / cos(x) - ## Computes the secant of ``x``. + ## Computes the secant of ``x`` (1 / cos(x)). proc csc*[T: float32|float64](x: T): T = 1.0 / sin(x) - ## Computes the cosecant of ``x``. + ## Computes the cosecant of ``x`` (1 / sin(x)). proc coth*[T: float32|float64](x: T): T = 1.0 / tanh(x) - ## Computes the hyperbolic cotangent of ``x``. + ## Computes the hyperbolic cotangent of ``x`` (1 / tanh(x)). proc sech*[T: float32|float64](x: T): T = 1.0 / cosh(x) - ## Computes the hyperbolic secant of ``x``. + ## Computes the hyperbolic secant of ``x`` (1 / cosh(x)). proc csch*[T: float32|float64](x: T): T = 1.0 / sinh(x) - ## Computes the hyperbolic cosecant of ``x``. + ## Computes the hyperbolic cosecant of ``x`` (1 / sinh(x)). proc arccot*[T: float32|float64](x: T): T = arctan(1.0 / x) ## Computes the inverse cotangent of ``x``. @@ -352,11 +562,17 @@ when not defined(JS): # C ## echo hypot(4.0, 3.0) ## 5.0 proc pow*(x, y: float32): float32 {.importc: "powf", header: "<math.h>".} proc pow*(x, y: float64): float64 {.importc: "pow", header: "<math.h>".} - ## computes x to power raised of y. + ## Computes x to power raised of y. + ## + ## To compute power between integers (e.g. 2^6), use `^ proc<#^,T,Natural>`_. ## - ## To compute power between integers, use ``^`` e.g. 2 ^ 6 + ## See also: + ## * `^ proc<#^,T,Natural>`_ + ## * `sqrt proc <#sqrt,float64>`_ + ## * `cbrt proc <#cbrt,float64>`_ ## ## .. code-block:: nim + ## echo pow(100, 1.5) ## 1000.0 ## echo pow(16.0, 0.5) ## 4.0 # TODO: add C89 version on windows @@ -370,6 +586,15 @@ when not defined(JS): # C proc gamma*(x: float32): float32 {.importc: "tgammaf", header: "<math.h>".} proc gamma*(x: float64): float64 {.importc: "tgamma", header: "<math.h>".} ## Computes the the `gamma function <https://en.wikipedia.org/wiki/Gamma_function>`_ for ``x``. + ## + ## See also: + ## * `lgamma proc <#lgamma,float64>`_ for a natural log of gamma function + ## + ## .. code-block:: Nim + ## echo gamma(1.0) # 1.0 + ## echo gamma(4.0) # 6.0 + ## echo gamma(11.0) # 3628800.0 + ## echo gamma(-1.0) # nan proc tgamma*(x: float32): float32 {.deprecated: "use gamma instead", importc: "tgammaf", header: "<math.h>".} proc tgamma*(x: float64): float64 @@ -379,19 +604,43 @@ when not defined(JS): # C proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "<math.h>".} proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "<math.h>".} ## Computes the natural log of the gamma function for ``x``. + ## + ## See also: + ## * `gamma proc <#gamma,float64>`_ for gamma function + ## + ## .. code-block:: Nim + ## echo lgamma(1.0) # 1.0 + ## echo lgamma(4.0) # 1.791759469228055 + ## echo lgamma(11.0) # 15.10441257307552 + ## echo lgamma(-1.0) # inf proc floor*(x: float32): float32 {.importc: "floorf", header: "<math.h>".} proc floor*(x: float64): float64 {.importc: "floor", header: "<math.h>".} ## Computes the floor function (i.e., the largest integer not greater than ``x``). ## + ## See also: + ## * `ceil proc <#ceil,float64>`_ + ## * `round proc <#round,float64>`_ + ## * `trunc proc <#trunc,float64>`_ + ## ## .. code-block:: nim + ## echo floor(2.1) ## 2.0 + ## echo floor(2.9) ## 2.0 ## echo floor(-3.5) ## -4.0 proc ceil*(x: float32): float32 {.importc: "ceilf", header: "<math.h>".} proc ceil*(x: float64): float64 {.importc: "ceil", header: "<math.h>".} - ## Computes the ceiling function (i.e., the smallest integer not less than ``x``). + ## Computes the ceiling function (i.e., the smallest integer not smaller + ## than ``x``). + ## + ## See also: + ## * `floor proc <#floor,float64>`_ + ## * `round proc <#round,float64>`_ + ## * `trunc proc <#trunc,float64>`_ ## ## .. code-block:: nim + ## echo ceil(2.1) ## 3.0 + ## echo ceil(2.9) ## 3.0 ## echo ceil(-2.1) ## -2.0 when windowsCC89: @@ -452,26 +701,50 @@ when not defined(JS): # C else: proc round*(x: float32): float32 {.importc: "roundf", header: "<math.h>".} proc round*(x: float64): float64 {.importc: "round", header: "<math.h>".} - ## Rounds a float to zero decimal places. Used internally by the round - ## function when the specified number of places is 0. + ## Rounds a float to zero decimal places. + ## + ## Used internally by the `round proc <#round,T,int>`_ + ## when the specified number of places is 0. + ## + ## See also: + ## * `round proc <#round,T,int>`_ for rounding to the specific + ## number of decimal places + ## * `floor proc <#floor,float64>`_ + ## * `ceil proc <#ceil,float64>`_ + ## * `trunc proc <#trunc,float64>`_ + ## + ## .. code-block:: nim + ## echo round(3.4) ## 3.0 + ## echo round(3.5) ## 4.0 + ## echo round(4.5) ## 5.0 proc trunc*(x: float32): float32 {.importc: "truncf", header: "<math.h>".} proc trunc*(x: float64): float64 {.importc: "trunc", header: "<math.h>".} ## Truncates ``x`` to the decimal point. ## + ## See also: + ## * `floor proc <#floor,float64>`_ + ## * `ceil proc <#ceil,float64>`_ + ## * `round proc <#round,float64>`_ + ## ## .. code-block:: nim ## echo trunc(PI) # 3.0 ## echo trunc(-1.85) # -1.0 proc fmod*(x, y: float32): float32 {.deprecated: "use mod instead", importc: "fmodf", header: "<math.h>".} proc fmod*(x, y: float64): float64 {.deprecated: "use mod instead", importc: "fmod", header: "<math.h>".} + ## **Deprecated since version 0.19.0**: Use the `mod proc + ## <#mod,float64,float64>`_ instead. + ## ## Computes the remainder of ``x`` divided by ``y``. - ## **Deprecated since version 0.19.0**: Use the ``mod`` operator instead. proc `mod`*(x, y: float32): float32 {.importc: "fmodf", header: "<math.h>".} proc `mod`*(x, y: float64): float64 {.importc: "fmod", header: "<math.h>".} ## Computes the modulo operation for float values (the remainder of ``x`` divided by ``y``). ## + ## See also: + ## * `floorMod proc <#floorMod,T,T>`_ for Python-like (% operator) behavior + ## ## .. code-block:: nim ## ( 6.5 mod 2.5) == 1.5 ## (-6.5 mod 2.5) == -1.5 @@ -502,16 +775,22 @@ else: # JS ## (-6.5 mod -2.5) == -1.5 proc round*[T: float32|float64](x: T, places: int): T {.deprecated: "use format instead".} = + ## **Deprecated:** use `strformat module <strformat.html>`_ + ## ## Decimal rounding on a binary floating point number. ## ## This function is NOT reliable. Floating point numbers cannot hold - ## non integer decimals precisely. If ``places`` is 0 (or omitted), + ## non integer decimals precisely. If ``places`` is 0 (or omitted), ## round to the nearest integral value following normal mathematical - ## rounding rules (e.g. ``round(54.5) -> 55.0``). If ``places`` is + ## rounding rules (e.g. ``round(54.5) -> 55.0``). If ``places`` is ## greater than 0, round to the given number of decimal places, - ## e.g. ``round(54.346, 2) -> 54.350000000000001421...``. If ``places`` is negative, round - ## to the left of the decimal place, e.g. ``round(537.345, -1) -> + ## e.g. ``round(54.346, 2) -> 54.350000000000001421…``. If ``places`` is negative, round + ## to the left of the decimal place, e.g. ``round(537.345, -1) -> ## 540.0`` + ## + ## .. code-block:: Nim + ## echo round(PI, 2) ## 3.14 + ## echo round(PI, 4) ## 3.1416 if places == 0: result = round(x) else: @@ -520,9 +799,14 @@ proc round*[T: float32|float64](x: T, places: int): T {.deprecated: "use format proc floorDiv*[T: SomeInteger](x, y: T): T = ## Floor division is conceptually defined as ``floor(x / y)``. - ## This is different from the ``div`` operator, which is defined - ## as ``trunc(x / y)``. That is, ``div`` rounds towards ``0`` and ``floorDiv`` - ## rounds down. + ## + ## This is different from the `system.div <system.html#div,int,int>`_ + ## operator, which is defined as ``trunc(x / y)``. + ## That is, ``div`` rounds towards ``0`` and ``floorDiv`` rounds down. + ## + ## See also: + ## * `system.div proc <system.html#div,int,int>`_ for integer division + ## * `floorMod proc <#floorMod,T,T>`_ for Python-like (% operator) behavior ## ## .. code-block:: nim ## echo floorDiv( 13, 3) # 4 @@ -535,8 +819,13 @@ proc floorDiv*[T: SomeInteger](x, y: T): T = proc floorMod*[T: SomeNumber](x, y: T): T = ## Floor modulus is conceptually defined as ``x - (floorDiv(x, y) * y)``. + ## ## This proc behaves the same as the ``%`` operator in Python. ## + ## See also: + ## * `mod proc <#mod,float64,float64>`_ + ## * `floorDiv proc <#floorDiv,T,T>`_ + ## ## .. code-block:: nim ## echo floorMod( 13, 3) # 1 ## echo floorMod(-13, 3) # 2 @@ -552,6 +841,7 @@ when not defined(JS): importc: "frexp", header: "<math.h>".} proc frexp*[T, U](x: T, exponent: var U): T = ## Split a number into mantissa and exponent. + ## ## ``frexp`` calculates the mantissa m (a float greater than or equal to 0.5 ## and less than 1) and the integer value n such that ``x`` (the original ## float value) equals ``m * 2**n``. frexp stores n in `exponent` and returns @@ -584,7 +874,19 @@ when not defined(JS): else: proc log2*(x: float32): float32 {.importc: "log2f", header: "<math.h>".} proc log2*(x: float64): float64 {.importc: "log2", header: "<math.h>".} - ## Computes the binary logarithm (base 2) of ``x`` + ## Computes the binary logarithm (base 2) of ``x``. + ## + ## See also: + ## * `log proc <#log,T,T>`_ + ## * `log10 proc <#log10,float64>`_ + ## * `ln proc <#ln,float64>`_ + ## * `exp proc <#exp,float64>`_ + ## + ## .. code-block:: Nim + ## echo log2(8.0) # 3.0 + ## echo log2(1.0) # 0.0 + ## echo log2(0.0) # -inf + ## echo log2(-2.0) # nan else: proc frexp*[T: float32|float64](x: T, exponent: var int): T = @@ -613,7 +915,8 @@ proc splitDecimal*[T: float32|float64](x: T): tuple[intpart: T, floatpart: T] = ## function in C. ## ## .. code-block:: nim - ## echo splitDecimal(5.25) # (intpart: 5.0, floatpart: 0.25) + ## echo splitDecimal(5.25) # (intpart: 5.0, floatpart: 0.25) + ## echo splitDecimal(-2.73) # (intpart: -2.0, floatpart: -0.73) var absolute: T absolute = abs(x) @@ -626,26 +929,36 @@ proc splitDecimal*[T: float32|float64](x: T): tuple[intpart: T, floatpart: T] = {.pop.} proc degToRad*[T: float32|float64](d: T): T {.inline.} = - ## Convert from degrees to radians + ## Convert from degrees to radians. + ## + ## See also: + ## * `radToDeg proc <#radToDeg,T>`_ ## ## .. code-block:: nim ## echo degToRad(180.0) # 3.141592653589793 result = T(d) * RadPerDeg proc radToDeg*[T: float32|float64](d: T): T {.inline.} = - ## Convert from radians to degrees - + ## Convert from radians to degrees. + ## + ## See also: + ## * `degToRad proc <#degToRad,T>`_ + ## ## .. code-block:: nim ## echo degToRad(2 * PI) # 360.0 result = T(d) / RadPerDeg proc sgn*[T: SomeNumber](x: T): int {.inline.} = - ## Sign function. Returns -1 for negative numbers and ``NegInf``, 1 for - ## positive numbers and ``Inf``, and 0 for positive zero, negative zero and - ## ``NaN``. + ## Sign function. + ## + ## Returns: + ## * `-1` for negative numbers and ``NegInf``, + ## * `1` for positive numbers and ``Inf``, + ## * `0` for positive zero, negative zero and ``NaN`` ## ## .. code-block:: nim - ## echo sgn(-5) # 1 + ## echo sgn(5) # 1 + ## echo sgn(0) # 0 ## echo sgn(-4.1) # -1 ord(T(0) < x) - ord(x < T(0)) @@ -653,11 +966,20 @@ proc sgn*[T: SomeNumber](x: T): int {.inline.} = {.pop.} proc `^`*[T](x: T, y: Natural): T = - ## Computes ``x`` to the power ``y``. ``x`` must be non-negative, use - ## `pow <#pow,float,float>`_ for negative exponents. + ## Computes ``x`` to the power ``y``. + ## + ## Exponent ``y`` must be non-negative, use + ## `pow proc <#pow,float64,float64>`_ for negative exponents. + ## + ## See also: + ## * `pow proc <#pow,float64,float64>`_ for negative exponent or + ## floats + ## * `sqrt proc <#sqrt,float64>`_ + ## * `cbrt proc <#cbrt,float64>`_ ## ## .. code-block:: nim - ## echo 2 ^ 3 # 8 + ## echo 2^3 # 8 + ## echo -2^3 # -8 when compiles(y >= T(0)): assert y >= T(0) else: @@ -675,9 +997,16 @@ proc `^`*[T](x: T, y: Natural): T = proc gcd*[T](x, y: T): T = ## Computes the greatest common (positive) divisor of ``x`` and ``y``. + ## ## Note that for floats, the result cannot always be interpreted as ## "greatest decimal `z` such that ``z*N == x and z*M == y`` ## where N and M are positive integers." + ## + ## See also: + ## * `gcd proc <#gcd,SomeInteger,SomeInteger>`_ for integer version + ## * `lcm proc <#lcm,T,T>`_ + runnableExamples: + doAssert gcd(13.5, 9.0) == 4.5 var (x, y) = (x, y) while y != 0: x = x mod y @@ -685,11 +1014,15 @@ proc gcd*[T](x, y: T): T = abs x proc gcd*(x, y: SomeInteger): SomeInteger = - ## Computes the greatest common (positive) divisor of ``x`` and ``y``. - ## Using binary GCD (aka Stein's) algorithm. + ## Computes the greatest common (positive) divisor of ``x`` and ``y``, + ## using binary GCD (aka Stein's) algorithm. ## - ## .. code-block:: nim - ## echo gcd(24, 30) # 6 + ## See also: + ## * `gcd proc <#gcd,T,T>`_ for floats version + ## * `lcm proc <#lcm,T,T>`_ + runnableExamples: + doAssert gcd(12, 8) == 4 + doAssert gcd(17, 63) == 1 when x is SomeSignedInt: var x = abs(x) else: @@ -716,10 +1049,15 @@ proc gcd*(x, y: SomeInteger): SomeInteger = proc lcm*[T](x, y: T): T = ## Computes the least common multiple of ``x`` and ``y``. ## - ## .. code-block:: nim - ## echo lcm(24, 30) # 120 + ## See also: + ## * `gcd proc <#gcd,T,T>`_ + runnableExamples: + doAssert lcm(24, 30) == 120 + doAssert lcm(13, 39) == 39 x div gcd(x, y) * y + + when isMainModule and not defined(JS) and not windowsCC89: # Check for no side effect annotation proc mySqrt(num: float): float {.noSideEffect.} = |