math library

Joshua Shinavier edited this page May 23, 2011 · 11 revisions

The math: library contains primitives for basic arithmetic, trigonometry, and so on. Most of these primitives are based on common functions available in general-purpose math libraries, which can simply be wrapped by a Ripple implementation. However, Ripple imposes a few conditions on datatypes and semantics, and does not constrain results to single solutions. For example, division by zero simply results in no solutions (rather than an error), while the square root of a (positive) number has two solutions. In other cases, only the principal value of a multiple-valued function is produced (e.g. in the case of the inverse trigonometric functions, which may have infinitely many solutions).

Arithmetic and basic math

There are two forms of arithmetic in Ripple: integer arithmetic and floating-point arithmetic. The same primitives are used for each. For example, the expression 10 3 div. evaluates to 3 using integer arithmetic (as the operands 10 and 3 are both integer values), while the mathematically equivalent 10 3e0 div. evaluates to 3.3333333333333335E0 or similar, depending on the environment, using floating-point arithmetic because 3e0 is a double-precision value.

Ripple uses the following numeric datatypes, in order of preference: xsd:integer, xsd:long, xsd:float, xsd:double, and xsd:decimal. When applying arguments of different datatypes in the same calculation, a Ripple implementation chooses the datatype with the higher preference as the datatype of any solutions. The other argument(s) to the primitive are cast to that datatype, then the calculation is performed using integer arithmetic if the datatype is xsd:integer or xsd:long, or floating-point arithmetic if the datatype is xsd:float, xsd:double, or xsd:decimal.

abs

This primitive finds the absolute value of a number. It expects a single, numeric argument at the top of the stack. It pops the argument from the stack and pushes its absolute value.

The inverse of abs pops a non-negative value from the stack and pushes each of the value itself and (for positive numbers), the negation of the value.

Examples:

1)  42 abs.

  [1]  42

2)  -100 abs.

  [1]  100

3)  3.1415 abs~.

  [1]  3.1415
  [2]  -3.1415

add

This primitive finds the sum of two numbers. It expects two, numeric arguments at the top of the stack: the operands to the add operation. It pops the operands from the stack and pushes their sum.

The inverse of add is sub (see below).

Example:

1)  2 3 add.

  [1]  5

2)  2 3 add~.

  [1]  -1

ceil

This primitive finds the ceiling of a number, i.e. the lowest integer greater than or equal to the number. It expects a single, numeric argument at the top of the stack: the operand. It pops the operand from the stack and pushes the operand's ceiling value.

This primitive has no special inverse.

Examples:

1)  3.1415 ceil.

  [1]  4

2)  42 ceil.

  [1]  42

3)  -123.45 ceil.

  [1]  -123

div

This primitive finds the quotient of one number divided by another. It expects two, numeric arguments at the top of the stack: the dividend and the divisor. It pops the operands from the stack and pushes their quotient. If the divisor is equal to zero, no solution is produced.

The inverse of div is mul (see below).

Examples:

1)  42 6 div.

  [1]  7

2)  1 0 div.

3)  2 3 div~.

  [1]  6

floor

This primitive finds the floor of a number, i.e. the highest integer less than or equal to the number. It expects a single, numeric argument at the top of the stack. It pops the argument from the stack and pushes the argument's floor value.

This primitive has no special inverse.

Examples:

1)  137 floor.

  [1]  137

2)  -1.4142 floor.

  [1]  -2

mod

This primitive finds the remainder after dividing a given number by a given modulus. It expects two, numeric arguments at the top of the stack: the dividend and the modulus. It pops the dividend and modulus from the stack, divides the dividend by the modulus, and pushes the remainder to the stack.

This primitive has no special inverse.

Examples:

1)  42 2 mod.

  [1]  0

2)  23 2e0 mod.

  [1]  1.0E0

mul

This primitive finds the product of two numbers. It expects two, numeric arguments at the top of the stack: the multiplicands. The multiplicands are popped from the stack and multiplied, then their product is pushed onto the stack.

The inverse of mul is div (see above).

Examples:

1)  6 9 mul.

  [1]  54

2)  6 9e0 mul~.

  [1]  0.6666666666666666E0

neg

This primitive finds the additive inverse of a number. It expects one, numeric argument at the top of the stack. It pops the argument off of the stack, then pushes its inverse.

This primitive is its own inverse.

Examples:

1)  42 neg.

  [1]  -42

2)  0 neg.

  [1]  0

3)  42 neg~.   

  [1]  -42

pow

This primitive raises a given number to a given power. It expects two arguments at the top of the stack: a multiplicand and the "power" p. It pops the arguments from the stack and pushes the value of the multiplicand to the power of p.

The inverse of this primitive is the logarithm whose base is the multiplicand. It behaves like "roots and exponentials" primitives (see below) in that it always converts its arguments to floating-point values.

Examples:

1)  2 3 pow.

  [1]  8

2)  2 8 pow~.

  [1]  3.0E0

sign

This primitive is the signum function, which finds whether a number is negative, zero, or positive. It expects a single, numeric argument at the top of the stack. It pops the argument off of the stack and pushes:

  • -1 if the number is less than zero. or
  • 0 if the number is equal to zero, or
  • 1 if the number is greater than zero

This primitive has no special inverse.

Examples:

  [1]  1

2)  -2 sign.

  [1]  -1

3)  42 dup. sub. sign.

  [1]  0

sub

This primitive finds the difference between two numbers. It expects two, numeric arguments at the top of the stack: the minuend and the subtrahend. It pops the arguments from the stack and pushes their difference.

The inverse of sub is add (see above).

Examples:

1)  0 1 sub.

  [1]  -1

2)  0 1 sub~.

  [1]  1

Roots and exponentials

These primitive deal with real-valued multiplication. All of them use floating point arithmetic regardless of the type of their arguments (although in some cases, the inverse of a primitive may use integer arithmetic).

cbrt

This primitive finds the real cube root of a number. The semantics of cbrt are such that every number has exactly one cube root. It expects a single, numeric argument at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes its cube root to the stack.

The inverse of this primitive is the (anonymous) cube function, which pops a number from the stack and pushes the third power of the number.

Examples:

1)  8 cbrt.

  [1]  2.0E0

2)  10 cbrt.

  [1]  2.154434690031884E0

3)  10 cbrt~.

  [1]  1000

exp

This primitive is the exponential function. It expects one, numeric argument at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, and pushes [Euler's constant](http://en.wikipedia.org/wiki/E_(mathematical_constant) to the power of that number.

The inverse of exp is log (see below).

Examples:

1)  1 exp.

  [1]  2.7182818284590455E0

2)  0 exp.

  [1]  1.0E0

3)  -1 exp.

  [1]  0.36787944117144233E0

4)  2.718 exp~.

  [1]  0.999896315728952E0

log

This primitive finds the natural logarithm of a number. It expects a single, numeric argument at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, and pushes its natural logarithm.

The inverse of log is exp (see above).

Examples:

1)  1 log.

  [1]  0.0E0

2)  10 log.

  [1]  2.302585092994046E0

3)  1 log~.

  [1]  2.7182818284590455E0

log10

This primitive finds the base-10 logarithm of a number. It expects a single, numeric argument at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, and pushes its natural logarithm.

The inverse of log pops a single, numeric argument from the stack and pushes the value of 10 to the power (as in pow above) of that number.

Examples:

1)  1 log10.

  [1]  0.0E0

2)  10 log10.

  [1]  1.0E0

3)  3 log10~.

  [1]  1000

sqrt

This primitive finds the real square root(s) of a number. The semantics of sqrt are such that every positive number has two square roots, the number 0 has one square root, and negative numbers have no square roots. It expects a single, numeric argument at the top of the stack. It pops the argument from the stack and, for each square root, pushes the square root to the stack.

The inverse of this primitive is the (anonymous) square function, which pops one argument from the stack and pushes the result of multiplying that number with itself.

Examples:

1)  2 sqrt.

  [1]  1.4142135623730951E0
  [2]  -1.4142135623730951E0

2)  -2 sqrt.

3)  2 sqrt~.

  [1]  4

Trigonometry

These primitives deal with trigonometric and hyperbolic functions. All of these primitives cast their arguments to floating-point values, and produce only floating-point values in solutions.

acos

This primitive finds the principal arccosine of a number. It expects a single, numeric value at the top of the stack which lies in the interval [-1, 1]. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the principal arccosine of the argument.

The inverse of acos is cos (see below).

Example:

1)  1 acos.

  [1]  0.0E0

2)  0 acos.

  [1]  1.5707963267948966E0

3)  -1 acos.

  [1]  3.141592653589793E0

asin

This primitive finds the principal arcsine of a number. It expects a single, numeric value at the top of the stack which lies in the interval [-1, 1]. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the principal arcsine of the argument.

The inverse of asin is sin (see below).

Example:

1)  0 asin.

  [1]  0.0E0

2)  -1 asin.

  [1]  -1.5707963267948966E0

3)  2 sqrt. 2 div. asin. 4 mul.

  [1]  3.1415926535897936E0
  [2]  -3.1415926535897936E0

atan

This primitive finds the principal arctangent of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the principal arctangent of the argument.

The inverse of atan is tan (see below).

Example:

1)  0 atan.

  [1]  0.0E0

2)  -1 atan. 4 mul.

  [1]  -3.141592653589793E0

atan2

This primitive applies the atan2 function to two numbers x and y, finding the angle between the positive x axis and the vector (x, y). It expects two, numeric values at the top of the stack: x and y. It pops the arguments from the stack, converts them to a floating-point values if necessary, then pushes their atan2 value.

This primitive has no specially-defined inverse.

Example:

1)  1 1 atan2.

  [1]  0.7853981633974483E0

2)  -1 -1 atan2.

  [1]  -2.356194490192345E0

cos

This primitive finds the cosine of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the cosine of the argument.

The inverse of cos is acos (see above).

Example:

1)  0 cos.

  [1]  1.0E0

2)  3.141592653589793 cos.

  [1]  -1.0E0

3)  2 sqrt. 2 div. cos~. 4 mul.

  [1]  3.141592653589793E0
  [2]  9.42477796076938E0

cosh

This primitive finds the hyperbolic cosine of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the hyperbolic cosine of the argument.

This primitive is not required to have a non-trivial inverse. However, if one is defined, it should implement the inverse hyperbolic cosine function, producing at least the principal value of the function as a solution for any given argument.

Example:

1)  0 cosh.

  [1]  1.0E0

2)  -1 cosh.

  [1]  1.543080634815244E0

sin

This primitive finds the sine of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the sine of the argument.

The inverse of sin is asin (see above).

Example:

1)  0 sin.

  [1]  0.0E0

2)  1.5707963267948966 sin.

  [1]  1.0E0

sinh

This primitive finds the hyperbolic sine of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the hyperbolic sine of the argument.

This primitive is not required to have a non-trivial inverse. However, if one is defined, it should implement the inverse hyperbolic sine function.

Example:

1)  0 sinh.

  [1]  0.0E0

2)  -1 sinh.

  [1]  -1.1752011936438014E0

tan

This primitive finds the tangent of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the tangent of the argument.

The inverse of tan is atan (see above).

Example:

1)  0 tan.

  [1]  0.0E0

2)  3.141592653589793 4 div. tan.

  [1]  0.9999999999999999E0

3)  1 tan~.

  [1]  0.7853981633974483E0

tanh

This primitive finds the hyperbolic tangent of a number. It expects a single, numeric value at the top of the stack. It pops the argument from the stack, converts it to a floating-point value if necessary, then pushes the hyperbolic tangent of the argument.

This primitive is not required to have a non-trivial inverse. However, if one is defined, it should implement the inverse hyperbolic tangent function.

Example:

1)  0 tanh.

  [1]  0.0E0

2)  -1 tanh.

  [1]  -0.7615941559557649E0