# `ExpressionMath` (Python)¶

ExpressionMath is a C++/Python Library that provides access to commonly used graphics functions.

All functions listed below are pre-imported in the context of parameter expressions, so you can use them directly, for example: `lerp(0.5, 1, 12)`

In a Python tab or shelf script, the functions are available from the ExpressionMath module, for example: `ExpressionMath.lerp(0.5, 1, 12)`

## Utilities¶

ExpressionMath.ifelse(expression, a, b)

If expression evaluates to True, return object a. Otherwise, return object b.

Warning

BOTH inputs (a and b) are evaluated, no matter what the expression evaluates to. Unfortunately. this is inherent to Python argument handling and is not fixable.

ExpressionMath.clamp(value, a, b)

Return value, clamped between the extremes a and b. It is not necessary for `b > a`. Mixed scalar / vector inputs are supported for all arguments.

```>>> clamp(-0.5, 0.1, 0.9)
0.1
>>> clamp(-0.5, 0.9, 0.1)
0.1
>>> clamp((-0.5,0.0,0.5,1.0), 0.1, 0.9)
(0.1, 0.1, 0.5, 0.9)
```
ExpressionMath.lerp(mix, a, b)

Return a linear interpolation between a and b, combined using the fraction mix. mix is not clamped between [0,1]. A mix value of 0.0 returns a. Mixed scalar / vector inputs are supported for all arguments.

```>>> lerp(0.0, 10, 20)
10.0
>>> lerp(0.5, 10, 20)
15.0
>>> lerp(1.5, 10, 20)
25.0
>>> lerp((0.0,0.5,1.5), 10, 20)
(10.0, 15.0, 25.0)
>>> lerp(0.5, 10, (20,30,40))
(15.0, 20.0, 25.0)
```
ExpressionMath.smoothstep(t)

Compute a smoothstep (ease in, ease out) version of t: [0,1]. This will clamp the output to [0,1].

Both scalar and vector input is supported.

Note

This is the ‘classic’ smoothstep: `3t**2 - 2t**3`, rather Perlin  modified smoothstep: `6t**5 - 15t**4 + 10t**3`. The two are quite similar, the differences being that Perlin’s smoothstep has zero 1st and 2nd derivatives at `t=0` and `t=1`, and is thus generally preferred for general use.

```>>> smoothstep(0.2)
0.05792
>>> smoothstep((-0.5, 0.0, 0.25, 0.5, 0.75, 1.0, 1.5))
(0.0, 0.0, 0.103515625, 0.5, 0.896484375, 1.0, 1.0)
```
ExpressionMath.fit(value, oldmin, oldmax, newmin, newmax)

Returns a number between newmin and newmax, which is relative to value in the range between oldmin and oldmax.

Mixed scalar / vector inputs are supported for all arguments.

```>>> fit(0, -1, 1, 10, 20)
15.0
>>> fit(2, -1, 1, 10, 20)
25.0
>>> fit((-1,0.5,0.5,1), -1, 1, 10, 20)
(10.0, 17.5, 17.5, 20.0)
```
ExpressionMath.cfit(value, oldmin, oldmax, newmin, newmax)

Same as fit, but the result is clamped to [newmin, newmax].

Mixed scalar / vector inputs are supported for all arguments.

```>>> cfit(0, -1, 1, 10, 20)
15.0
>>> cfit(2, -1, 1, 10, 20)
20.0
>>> cfit((-1,0.5,0.5,1), -1, 1, 10, 20)
(10.0, 17.5, 17.5, 20.0)
```
ExpressionMath.softcfit(value, oldmin, oldmax, newmin, newmax)

Same as cfit, but value is interpolates between oldmin and oldmax using `smoothstep()`.

Mixed scalar / vector inputs are supported for all arguments.

```>>> softcfit(0, -1, 1, 10, 20)
15.0
>>> softcfit(2, -1, 1, 10, 20)
20.0
>>> softcfit((-1,0.5,0.5,1), -1, 1, 10, 20)
(10.0, 18.96484375, 18.96484375, 20.0)
```
ExpressionMath.retime(frame, start, end, inMode, outMode)

Performs frame interpolation using specified hold mode: ‘freeze’, ‘repeat’, or ‘mirror’.

freeze

Hold the first/last frame of the sequence: `1111 1234 4444`

repeat

Repeat the sequence: `1234 1234 1234`

mirror

Mirror the sequence, end points are only used once: `3432 1234 3212`

Note

Repeat mode may generate values outside of [start, end] at non-integer time samples (due to extrapolation).

Supports float input for {frame, start, end}. It is not necessary for `start < end` (though `start != end`).

```>>> retime(110, 101, 110, 'repeat', 'repeat')
110.0
>>> retime(111, 101, 110, 'repeat', 'repeat')
101.0
>>> retime(112, 101, 110, 'repeat', 'repeat')
102.0
>>> retime(111, 101, 110, 'repeat', 'freeze')
110.0
>>> retime(112, 101, 110, 'repeat', 'freeze')
110.0
>>> retime(111, 101, 110, 'repeat', 'mirror')
109.0
>>> retime(112, 101, 110, 'repeat', 'mirror')
108.0
```

## Noise¶

ExpressionMath.noise(x [,y [,z [,w]]]])

Improved Perlin noise , contained within the range [0,1]. The noise is generated by smoothing interpolating a set a pseudo-random gradients at regularly spaced points in space (integer lattice locations). The statistical characteristics of this call closely approximates that of PRman’s noise operator. One, two, three, and four-dimensional interpolants are provided.

```>>> noise(0.0)
0.5
>>> noise(0.5)
0.40600001811981201
>>> noise(1.0)
0.5
>>> noise(0.5,0.5)
0.6901249885559082
>>> noise(0.5)
0.6901249885559082
```
ExpressionMath.snoise(x [,y [,z [,w]]]])

Signed equivalent of `noise()`.

```>>> snoise(0.0)
0.0
>>> snoise(0.5)
-0.18799999356269836
>>> snoise(1.0)
0.0
>>> snoise(0.5,0.5)
0.38025002181529999
```
ExpressionMath.randval(min, max, seedInt)

Return a random value between [min, max] using the specified seed integer. The distribution is identical to Splat’s randVal3 function.

```>>> randval(0,1,0)
0.22541344799693055
>>> randval(0,1,1)
0.16124458358652066
>>> randval(0,2,1)
0.32248916717304132
>>> [randval(0,1,frame) for frame in xrange(101,103)]
[0.77299156360630683, 0.83146012384245638, 0.099642227194188679]
```

## Hashing¶

ExpressionMath.stablehash(string)

Return a 32-bit signed integer hash of the specified string. This result is stable across architectures (i.e., you get the same answer on both 32- and 64-bit platforms.) This result is often useful for turning strings (such as scenegraph locations) into seedIntegers for use in randval (see above).

```>>> stablehash('')
2118318316
>>> stablehash('/root/world/lights/rig/key1')
-847711557
>>> stablehash('/root/world/lights/rig/key2')
652177629
```

## Floating Point¶

ExpressionMath.isinf(number)

Return whether the argument value is an infinity (positive or negative).

```>>> isinf(1.0)
False
>>> isinf(float('inf'))
True
```
ExpressionMath.isnan(number)

Return whether the argument value is a NaN.

```>>> isnan(1.0)
False
>>> isinf(float('nan'))
True
```
ExpressionMath.isfinite(number)

Return whether the argument value is a finite value (zero, subnormal, or normal, and not infinite or NaN).

```>>> isfinite(1.0)
True
>>> isfinite(float('nan'))
False
>>> isfinite(float('inf'))
False
>>> isfinite(float('-inf'))
False
```