Calls

%reload_ext rubberize
from rubberize.config import config

Built-in Class Calls

Class calls to instantiate built-in types are rendered as the resulting object:

%%tap --grid
from decimal import Decimal
from fractions import Fraction

int(42.3042)
float(69)
Decimal('0.00004291')
Fraction(0.3125)
\( \displaystyle 42 \)
\( \displaystyle 69.00 \)
\( \displaystyle 0.00004291 \)
\( \displaystyle \frac{5}{16} \)
%%tap --grid
list((3, 5, 6))
tuple([3, 5, 6])
set([3, 5, 6])
\( \displaystyle \left[ 3,\, 5,\, 6 \right] \)
\( \displaystyle \left( 3,\, 5,\, 6 \right) \)
\( \displaystyle \left\{ 3,\, 5,\, 6 \right\} \)
%%tap --grid
dict([("a", 1), ("b", 2)])
complex(3, 4)
range(25)
\( \displaystyle \left\{ \text{“a”} \to 1,\, \text{“b”} \to 2 \right\} \)
\( \displaystyle 3.00 + 4.00\,\mathrm{i} \)
\( \displaystyle \left( 0,\, 1,\, \cdots,\, 24 \right) \)

Built-in Functions

Most mathematical functions built into Python are rendered in math notation:

%%tap --grid
import math

abs(-40)
math.fabs(-42.0)
math.ceil(8008.135)
math.floor(8008.135)
\( \displaystyle \left| -40 \right| = 40 \)
\( \displaystyle \left| -42.00 \right| = 42.00 \)
\( \displaystyle \left\lceil 8\,008.14 \right\rceil = 8\,009 \)
\( \displaystyle \left\lfloor 8\,008.14 \right\rfloor = 8\,008 \)
%%tap --grid
math.comb(5, 3)
math.perm(5, 3)
math.exp(5)
math.exp(5/2)
\( \displaystyle \operatorname{C} \left( 5,\, 3 \right) = 10 \)
\( \displaystyle \operatorname{P} \left( 5,\, 3 \right) = 60 \)
\( \displaystyle e^{5} = 148.41 \)
\( \displaystyle \exp \left( \frac{5}{2} \right) = 12.18 \)
%%tap --grid
math.gamma(5)
math.factorial(10)
math.sqrt(3**2 + 4**2)
math.cbrt(3**2 + 4**2)
\( \displaystyle \Gamma \left( 5 \right) = 24.00 \)
\( \displaystyle 10! = 3\,628\,800 \)
\( \displaystyle \sqrt{3^{2} + 4^{2}} = 5.00 \)
\( \displaystyle \sqrt[3]{3^{2} + 4^{2}} = 2.92 \)

Trigonometric Functions

Trigonometric functions are rendered as unary functions. If its argument is a single value and not an expression, it is not wrapped in parentheses.

%%tap --grid
import pint

ureg = pint.UnitRegistry()  # @hide

math.sin(1.309)
math.sin(75 * ureg.deg)
math.sin(math.pi / 4 + math.pi / 6)
\( \displaystyle \sin 1.31 = 0.97 \)
\( \displaystyle \sin 75^{\circ} = 0.97 \)
\( \displaystyle \sin \left( \frac{\pi}{4} + \frac{\pi}{6} \right) = 0.97 \)

Logarithmic Functions

Rubberize follows the convention of using \(\displaystyle \log x\) for the common logarithm (base 10) and \(\displaystyle \ln x\) for the natural logarithm.

%%tap --grid
math.log(3)
math.log(3, 2)
math.log(3, math.e)
math.log(3, 10)
\( \displaystyle \ln 3 = 1.10 \)
\( \displaystyle \log_{2} 3 = 1.58 \)
\( \displaystyle \ln 3 = 1.10 \)
\( \displaystyle \log 3 = 0.48 \)
%%tap --grid
math.log10(3)
math.log1p(2)
math.log2(3)
\( \displaystyle \log 3 = 0.48 \)
\( \displaystyle \ln \left(1 + 2 \right) = 1.10 \)
\( \displaystyle \log_{2} 3 = 1.58 \)

Summation

The following summations are rendered in standard mathematical notation:

  • Summation of elements of an iterable
  • Summation using a generator expression for an iterable
  • Summation using a generator expression over a range
%%tap
A_vec = [12, 32, 18]
B_vec = [1, 8, 2]

sum(A_vec)  # Sum of elements
sum(3 * x for x in A_vec)  # Sum using a generator expression
sum(x + 1 for x in range(1, 6))  # Sum over a range
sum(x * y for x in A_vec for y in B_vec)  # Using two lists
sum((x**2 for x in range(5)), start=50) * 2  # With a start value
\( \displaystyle \mathbf{A} = \left[ 12,\, 32,\, 18 \right] \)
\( \displaystyle \mathbf{B} = \left[ 1,\, 8,\, 2 \right] \)
\( \displaystyle \sum \mathbf{A} = 62 \)
Sum of elements
\( \displaystyle \sum_{x \in \mathbf{A}} \left( 3\,x \right) = 186 \)
Sum using a generator expression
\( \displaystyle \sum_{x = 1}^{5} \left( x + 1 \right) = 20 \)
Sum over a range
\( \displaystyle \sum_{x \in \mathbf{A}}\,\sum_{y \in \mathbf{B}} \left( x\,y \right) = 682 \)
Using two lists
\( \displaystyle \left( 50 + \sum_{x = 0}^{4} \left( x^{2} \right) \right) \cdot 2 = 160 \)
With a start value

Pi Product

The same rendering rules also apply to pi products:

%%tap
A_vec = [12, 32, 18]
B_vec = [1, 8, 2]

math.prod(A_vec)  # Product of elements
math.prod(3 * x for x in A_vec)  # Product using a generator expression
math.prod(x + 1 for x in range(1, 6))  # Product over a range
math.prod(x - y for x in A_vec if x < 15 for y in B_vec)  # Using two lists
math.prod((x for x in range(1, 5)), start=50) + 2  # With a start value
\( \displaystyle \mathbf{A} = \left[ 12,\, 32,\, 18 \right] \)
\( \displaystyle \mathbf{B} = \left[ 1,\, 8,\, 2 \right] \)
\( \displaystyle \prod \mathbf{A} = 6\,912 \)
Product of elements
\( \displaystyle \prod_{x \in \mathbf{A}} \left( 3\,x \right) = 186\,624 \)
Product using a generator expression
\( \displaystyle \prod_{x = 1}^{5} \left( x + 1 \right) = 720 \)
Product over a range
\( \displaystyle \prod_{x \in \mathbf{A} \land x < 15}\,\prod_{y \in \mathbf{B}} \left( x - y \right) = 440 \)
Using two lists
\( \displaystyle 50 \cdot \prod_{x = 1}^{4} x + 2 = 1\,202 \)
With a start value

Aliased Functions

Function call transformations are resolved through a registry of converter functions registered with Rubberize. The registry is first consulted using the function object itself; if no match is found, the function name is used as a fallback. As a result, aliased functions are handled correctly:

%%tap
foo = max
foo(A_vec)
\( \displaystyle \mathrm{foo} = \mathrm{max} \)
\( \displaystyle \max \left( \mathbf{A} \right) = \max \left( \left[ 12,\, 32,\, 18 \right] \right) = 32 \)

Unknown Functions

If a function has no registered converter, the general form is used:

def max_a_b(a, *, b=10):
    return a if a > b else b

def foo(a, /, b, *args, **kwargs):
    return None
%%tap
max_a_b(3)
max_a_b(3, b=9)
foo(1, 2, *(3, 4), **{"a": 5})
\( \displaystyle \operatorname{max}_{a, b} \left( 3 \right) = 10 \)
\( \displaystyle \operatorname{max}_{a, b} \left( 3,\, b \leftarrow 9 \right) = 9 \)
\( \displaystyle \operatorname{foo} \left( 1,\, 2,\, *\left( 3,\, 4 \right),\, {**}\left\{ \text{“a”} \to 5 \right\} \right) \)

If needed, register_call_converter() can be used to define how Rubberize renders a specific function call. For a guide on creating a custom call converter, see the Custom Converters guide.

Suppressing Conversion

@convert_special_calls controls whether Rubberize applies special conversion rules to class and function calls:

config.convert_special_calls
True

When set to False, calls are rendered using the general form.

%%tap
math.exp(5)
math.exp(5)  # @convert_special_calls=False
\( \displaystyle e^{5} = 148.41 \)
\( \displaystyle \operatorname{exp} \left( 5 \right) = 148.41 \)