# Output a pseudo-random number in the interval [0, 1). Example:
#
# ```elvish-transcript
# ~> rand
# ▶ 0.17843564133528436
# ```
fn rand { }

# Constructs a [typed number](language.html#number).
#
# If the argument is a string, this command outputs the typed number the
# argument represents, or raises an exception if the argument is not a valid
# representation of a number. If the argument is already a typed number, this
# command outputs it as is.
#
# This command is usually not needed for working with numbers; see the
# discussion of [numeric commands](#numeric-commands).
#
# Examples:
#
# ```elvish-transcript
# ~> num 10
# ▶ (num 10)
# ~> num 0x10
# ▶ (num 16)
# ~> num 1/12
# ▶ (num 1/12)
# ~> num 3.14
# ▶ (num 3.14)
# ~> num (num 10)
# ▶ (num 10)
# ```
#
# See also [`exact-num`]() and [`inexact-num`]().
fn num {|string-or-number| }

# Coerces the argument to an exact number. If the argument is infinity or NaN,
# an exception is thrown.
#
# If the argument is a string, it is converted to a typed number first. If the
# argument is already an exact number, it is returned as is.
#
# Examples:
#
# ```elvish-transcript
# ~> exact-num (num 0.125)
# ▶ (num 1/8)
# ~> exact-num 0.125
# ▶ (num 1/8)
# ~> exact-num (num 1)
# ▶ (num 1)
# ```
#
# Beware that seemingly simple fractions that can't be represented precisely in
# binary can result in the denominator being a very large power of 2:
#
# ```elvish-transcript
# ~> exact-num 0.1
# ▶ (num 3602879701896397/36028797018963968)
# ```
#
# See also [`num`]() and [`inexact-num`]().
fn exact-num {|string-or-number| }

# Coerces the argument to an inexact number.
#
# If the argument is a string, it is converted to a typed number first. If the
# argument is already an inexact number, it is returned as is.
#
# Examples:
#
# ```elvish-transcript
# ~> inexact-num (num 1)
# ▶ (num 1.0)
# ~> inexact-num (num 0.5)
# ▶ (num 0.5)
# ~> inexact-num (num 1/2)
# ▶ (num 0.5)
# ~> inexact-num 1/2
# ▶ (num 0.5)
# ```
#
# Since the underlying representation for inexact numbers has limited range,
# numbers with very large magnitudes may be converted to an infinite value:
#
# ```elvish-transcript
# ~> inexact-num 1000000000000000000
# ▶ (num 1e+18)
# ~> inexact-num 10000000000000000000
# ▶ (num +Inf)
# ~> inexact-num -10000000000000000000
# ▶ (num -Inf)
# ```
#
# Likewise, numbers with very small magnitudes may be converted to 0:
#
# ```elvish-transcript
# ~> use math
# ~> math:pow 10 -323
# ▶ (num 1/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
# ~> inexact-num (math:pow 10 -323)
# ▶ (num 1e-323)
# ~> math:pow 10 -324
# ▶ (num 1/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
# ~> inexact-num (math:pow 10 -324)
# ▶ (num 0.0)
# ```
#
# See also [`num`]() and [`exact-num`]().
fn inexact-num {|string-or-number| }

# Constructs a floating-point number.
#
# This command is deprecated; use [`num`]() to construct a typed number, or
# [`inexact-num`]() to construct an inexact number.
fn float64 {|string-or-number| }

# ```elvish
# <  $number... # less
# <= $number... # less or equal
# == $number... # equal
# != $number... # not equal
# >  $number... # greater
# >= $number... # greater or equal
# ```
#
# Number comparisons. All of them accept an arbitrary number of arguments:
#
# 1.  When given fewer than two arguments, all output `$true`.
#
# 2.  When given two arguments, output whether the two arguments satisfy the named
# relationship.
#
# 3.  When given more than two arguments, output whether every adjacent pair of
# numbers satisfy the named relationship.
#
# Examples:
#
# ```elvish-transcript
# ~> == 3 3.0
# ▶ $true
# ~> < 3 4
# ▶ $true
# ~> < 3 4 10
# ▶ $true
# ~> < 6 9 1
# ▶ $false
# ```
#
# As a consequence of rule 3, the `!=` command outputs `$true` as long as any
# _adjacent_ pair of numbers are not equal, even if some numbers that are not
# adjacent are equal:
#
# ```elvish-transcript
# ~> != 5 5 4
# ▶ $false
# ~> != 5 6 5
# ▶ $true
# ```
#doc:id num-cmp
#doc:fn < <= == != > >=

# Outputs the sum of all arguments, or 0 when there are no arguments.
#
# This command is [exactness-preserving](#exactness-preserving).
#
# Examples:
#
# ```elvish-transcript
# ~> + 5 2 7
# ▶ (num 14)
# ~> + 1/2 1/3 1/4
# ▶ (num 13/12)
# ~> + 1/2 0.5
# ▶ (num 1.0)
# ```
#doc:id add
fn + {|@num| }

# Outputs the result of subtracting from `$x-num` all the `$y-num`s, working
# from left to right. When no `$y-num` is given, outputs the negation of
# `$x-num` instead (in other words, `- $x-num` is equivalent to `- 0 $x-num`).
#
# This command is [exactness-preserving](#exactness-preserving).
#
# Examples:
#
# ```elvish-transcript
# ~> - 5
# ▶ (num -5)
# ~> - 5 2
# ▶ (num 3)
# ~> - 5 2 7
# ▶ (num -4)
# ~> - 1/2 1/3
# ▶ (num 1/6)
# ~> - 1/2 0.3
# ▶ (num 0.2)
# ~> - 10
# ▶ (num -10)
# ```
#doc:id sub
fn - {|x-num @y-num| }

# Outputs the product of all arguments, or 1 when there are no arguments.
#
# This command is [exactness-preserving](#exactness-preserving). Additionally,
# when any argument is exact 0 and no other argument is a floating-point
# infinity, the result is exact 0.
#
# Examples:
#
# ```elvish-transcript
# ~> * 2 5 7
# ▶ (num 70)
# ~> * 1/2 0.5
# ▶ (num 0.25)
# ~> * 0 0.5
# ▶ (num 0)
# ```
#doc:id mul
fn * {|@num| }

# Outputs the result of dividing `$x-num` with all the `$y-num`s, working from
# left to right. When no `$y-num` is given, outputs the reciprocal of `$x-num`
# instead (in other words, `/ $y-num` is equivalent to `/ 1 $y-num`).
#
# Dividing by exact 0 raises an exception. Dividing by inexact 0 results with
# either infinity or NaN according to floating-point semantics.
#
# This command is [exactness-preserving](#exactness-preserving). Additionally,
# when `$x-num` is exact 0 and no `$y-num` is exact 0, the result is exact 0.
#
# Examples:
#
# ```elvish-transcript
# ~> / 2
# ▶ (num 1/2)
# ~> / 2.0
# ▶ (num 0.5)
# ~> / 10 5
# ▶ (num 2)
# ~> / 2 5
# ▶ (num 2/5)
# ~> / 2 5 7
# ▶ (num 2/35)
# ~> / 0 1.0
# ▶ (num 0)
# ~> / 2 0
# Exception: bad value: divisor must be number other than exact 0, but is exact 0
# [tty 6], line 1: / 2 0
# ~> / 2 0.0
# ▶ (num +Inf)
# ```
#
# When given no argument, this command is equivalent to `cd /`, due to the
# implicit cd feature. (The implicit cd feature will probably change to avoid
# this oddity).
#doc:id div
fn / {|x-num @y-num| }

# Outputs the remainder after dividing `$x` by `$y`. The result has the same
# sign as `$x`.
#
# Examples:
#
# ```elvish-transcript
# ~> % 10 3
# ▶ (num 1)
# ~> % -10 3
# ▶ (num -1)
# ~> % 10 -3
# ▶ (num 1)
# ```
#
# Note that `%` requires both arguments to be within the range of signed
# integers the size of a [machine
# word](https://en.wikipedia.org/wiki/Word_(computer_architecture)), and throws
# an exception otherwise:
#
# ```elvish-transcript
# ~> % (math:pow 2 63) 3
# Exception: wrong type for arg #0: must be integer
# ```
#
# This limit may be lifted in the future.
#doc:id rem
fn % {|x y| }

# Output a pseudo-random integer N such that `$low <= N < $high`. If not given,
# `$low` defaults to 0. Examples:
#
# ```elvish-transcript
# ~> # Emulate dice
# randint 1 7
# ▶ 6
# ```
fn randint {|low? high| }

# Sets the seed for the random number generator.
#doc:show-unstable
fn -randseed {|seed| }

# Outputs numbers, starting from `$start` and ending before `$end`, using
# `&step` as the increment.
#
# - If `$start` <= `$end`, `&step` defaults to 1, and `range` outputs values as
#   long as they are smaller than `$end`. An exception is thrown if `&step` is
#   given a negative value.
#
# - If `$start` > `$end`, `&step` defaults to -1, and `range` outputs values as
#   long as they are greater than `$end`. An exception is thrown if `&step` is
#   given a positive value.
#
# As a special case, if the outputs are floating point numbers, `range` also
# terminates if the values stop changing.
#
# This command is [exactness-preserving](#exactness-preserving).
#
# Examples:
#
# ```elvish-transcript
# ~> range 4
# ▶ (num 0)
# ▶ (num 1)
# ▶ (num 2)
# ▶ (num 3)
# ~> range 4 0
# ▶ (num 4)
# ▶ (num 3)
# ▶ (num 2)
# ▶ (num 1)
# ~> range -3 3 &step=2
# ▶ (num -3)
# ▶ (num -1)
# ▶ (num 1)
# ~> range 3 -3 &step=-2
# ▶ (num 3)
# ▶ (num 1)
# ▶ (num -1)
# ~> range (- (math:pow 2 53) 1) +inf
# ▶ (num 9007199254740991.0)
# ▶ (num 9007199254740992.0)
# ```
#
# When using floating-point numbers, beware that numerical errors can result in
# an incorrect number of outputs:
#
# ```elvish-transcript
# ~> range 0.9 &step=0.3
# ▶ (num 0.0)
# ▶ (num 0.3)
# ▶ (num 0.6)
# ▶ (num 0.8999999999999999)
# ```
#
# Avoid this problem by using exact rationals:
#
# ```elvish-transcript
# ~> range 9/10 &step=3/10
# ▶ (num 0)
# ▶ (num 3/10)
# ▶ (num 3/5)
# ```
#
# One usage of this command is to execute something a fixed number of times by
# combining with [each](#each):
#
# ```elvish-transcript
# ~> range 3 | each {|_| echo foo }
# foo
# foo
# foo
# ```
#
# Etymology:
# [Python](https://docs.python.org/3/library/functions.html#func-range).
fn range {|&step start=0 end| }
