summary refs log tree commit diff stats
path: root/lib/pure/math.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/math.nim')
-rw-r--r--lib/pure/math.nim516
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.} =