API Reference

dual_autodiff.dual

class dual_autodiff.dual.Dual(real, dual)[source]

Bases: object

A class to represent dual numbers, enabling basic operations and automatic differentiation.

__init__(real, dual)[source]

Initialize a dual number with its real and dual parts.

Parameters
  • real (float) – The real part of the dual number.

  • dual (float) – The dual part of the dual number.

static _validate_input(part_value, part)[source]

Validate the input for the real or dual part.

Parameters
  • part_value (float) – The input value to validate.

  • part (str) – The part of the dual number being validated.

Returns

The validated value.

Return type

float

Raises
  • TypeError – If ‘real part’ or ‘dual part’ is not a number.

  • ValueError – If ‘real part’ or ‘dual part’ is NaN or infinite.

__add__(other)[source]

Define addition for Dual numbers and scalars.

This method supports addition in both standard and reverse cases:
  • Dual + Dual

  • Dual + scalar

  • scalar + Dual (via __radd__)

Parameters

other (Dual, int, or float) – The value to add to the current Dual number.

Returns

A new Dual number representing the result of the addition.

Return type

Dual

Raises

TypeError – If ‘other’ is not a Dual, int, or float.

Examples:

  1. Dual + Dual:
    >>> x = Dual(2, 1)
    >>> y = Dual(3, 2)
    >>> x + y
    Dual(real=5, dual=3)
    
  2. Dual + scalar:
    >>> x = Dual(2, 1)
    >>> x + 3
    Dual(real=5, dual=1)
    
  3. Scalar + Dual:
    >>> x = Dual(2, 1)
    >>> 3 + x
    Dual(real=5, dual=1)
    
  4. Invalid input:
    >>> x = Dual(2, 1)
    >>> x + "string"
    Traceback (most recent call last):
        ...
    TypeError: Addition is only supported with Dual or scalar values.
    
__sub__(other)[source]

Define subtraction for Dual numbers and scalars.

This method supports subtraction in both standard and reverse cases:
  • Dual - Dual

  • Dual - scalar

  • scalar - Dual (via __rsub__)

Parameters

other (Dual, int, or float) – The value to subtract from the current Dual number.

Returns

A new Dual number representing the result of the subtraction.

Return type

Dual

Raises

TypeError – If ‘other’ is not a Dual, int, or float.

Examples:

  1. Dual - Dual:
    >>> x = Dual(5, 3)
    >>> y = Dual(2, 1)
    >>> x - y
    Dual(real=3, dual=2)
    
  2. Dual - scalar:
    >>> x = Dual(5, 3)
    >>> x - 2
    Dual(real=3, dual=3)
    
  3. Scalar - Dual:
    >>> x = Dual(5, 3)
    >>> 10 - x
    Dual(real=5, dual=-3)
    
  4. Invalid input:
    >>> x = Dual(5, 3)
    >>> x - "string"
    Traceback (most recent call last):
        ...
    TypeError: Subtraction is only supported with Dual or scalar values.
    
__mul__(other)[source]

Define multiplication for Dual numbers and scalars.

This method supports multiplication in both standard and reverse cases:
  • Dual * Dual

  • Dual * scalar

  • scalar * Dual (via __rmul__)

Parameters

other (Dual, int, or float) – The value to multiply with the current Dual number.

Returns

A new Dual number representing the result of the multiplication.

Return type

Dual

Raises

TypeError – If ‘other’ is not a Dual, int, or float.

Examples:

  1. Dual * Dual:
    >>> x = Dual(5, 3)
    >>> y = Dual(2, 1)
    >>> x * y
    Dual(real=10, dual=11)
    
  2. Dual * scalar:
    >>> x = Dual(5, 3)
    >>> x * 2
    Dual(real=10, dual=6)
    
  3. Scalar * Dual:
    >>> x = Dual(5, 3)
    >>> 2 * x
    Dual(real=10, dual=6)
    
  4. Invalid input:
    >>> x = Dual(5, 3)
    >>> x * "string"
    Traceback (most recent call last):
        ...
    TypeError: Multiplication is only supported with Dual or scalar values.
    
__truediv__(other)[source]

Define division for Dual numbers and scalars.

This method supports division in both standard and reverse cases:
  • Dual / Dual

  • Dual / scalar

  • scalar / Dual (via __rtruediv__)

Parameters

other (Dual, int, or float) – The value to divide by.

Returns

A new Dual number representing the result of the division.

Return type

Dual

Raises
  • TypeError – If ‘other’ is not a Dual, int, or float.

  • ZeroDivisionError – If dividing by zero (in the real part for Dual, or scalar zero).

Examples:

  1. Dual / Dual:
    >>> x = Dual(6, 4)
    >>> y = Dual(2, 1)
    >>> x / y
    Dual(real=3.0, dual=0.5)
    
  2. Dual / scalar:
    >>> x = Dual(6, 4)
    >>> x / 2
    Dual(real=3.0, dual=2.0)
    
  3. Scalar / Dual:
    >>> x = Dual(6, 4)
    >>> 12 / x
    Dual(real=2.0, dual=-1.3333...)
    
  4. Invalid input:
    >>> x = Dual(6, 4)
    >>> y = Dual(0, 1)
    >>> x / y
    Traceback (most recent call last):
        ...
    ZeroDivisionError: Cannot divide by a Dual number with no real part.
    
_dual_function(func, func_deriv)[source]

Internal method to apply a function to a dual number.

Supported Functions:
  • Sine: .sin()

  • Cosine: .cos()

  • Tangent: .tan()

  • Arcsin: .arcsin()

  • Arccos: .arccos()

  • Arctan: .arctan()

  • Sinh: .sinh()

  • Cosh: .cosh()

  • Tanh: .tanh()

  • Exponential: .exp()

  • Logarithm: .log()

  • Powers: .pow(n)

  • Square Root: .sqrt()

Parameters
  • func (callable) – The mathematical function applied to dual number.

  • func_deriv (callable) – The derivative of the function.

Returns

The out the function on a dual number

Return type

Dual

sin()[source]

Compute the sine of the Dual number.

Returns

Sine of original dual number

Return type

Dual

Examples

>>> x = Dual(2, 1)
>>> x.sin()
Dual(real=0.9092..., dual=-0.4161...)
cos()[source]

Compute the cosine of the Dual number.

Returns

Cosine of original dual number

Return type

Dual

Examples

>>> x = Dual(2, 1)
>>> x.cos()
Dual(real=-0.4161..., dual=-0.9093...)
tan()[source]

Compute the tangent of the Dual number.

Returns

Tangent of original dual number

Return type

Dual

Raises

ValueError – The tangent function is undefined as cosine of real part equals 0

Examples

>>> x = Dual(2, 1)
>>> x.tan()
Dual(real=-2.1850..., dual=5.7744...)
>>> Dual(math.pi / 2, 1).tan()
Traceback (most recent call last):
    ...
ValueError: Tangent undefined when cosine of real part equals 0.
exp()[source]

Compute the exponential of the Dual number.

Returns

Expontential of original dual number

Return type

Dual

Examples

>>> x = Dual(2, 1)
>>> x.exp()
Dual(real=7.3891..., dual=7.3891...)
log()[source]

Compute the natural logarithm of the Dual number.

Returns

Natural logirithim of original dual number

Return type

Dual

Raises

ValueError – If the real part of dual number is non-positive

Examples

>>> x = Dual(2, 1)
>>> x.log()
Dual(real=0.6931..., dual=0.5)
>>> x = Dual(0, 1)
>>> x.log()
Traceback (most recent call last):
    ...
ValueError: Logarithm is undefined for dual numbers with non-positive real parts.
arcsin()[source]

Compute the arcsine (inverse sine) of the Dual number.

Returns

Arcsine of the original Dual number.

Return type

Dual

Raises

ValueError – If the real part is outside the range [-1, 1].

Examples

>>> x = Dual(0.5, 1)
>>> x.arcsin()
Dual(real=0.5236..., dual=1.1547...)
>>> x = Dual(1.5, 1)
>>> x.arcsin()
Traceback (most recent call last):
    ...
ValueError: Arcsine is only defined for real parts in the range [-1, 1].
arccos()[source]

Compute the arccosine (inverse cosine) of the Dual number.

Returns

Arccosine of the original Dual number.

Return type

Dual

Raises

ValueError – If the real part is outside the range [-1, 1].

Examples

>>> x = Dual(0.5, 1)
>>> x.arccos()
Dual(real=1.0472..., dual=-1.1547...)
>>> x = Dual(-1.5, 1)
>>> x.arccos()
Traceback (most recent call last):
    ...
ValueError: Arccosine is only defined for real parts in the range [-1, 1].
arctan()[source]

Compute the arctangent (inverse tangent) of the Dual number.

Returns

Arctangent of the original Dual number.

Return type

Dual

Examples

>>> x = Dual(1, 1)
>>> x.arctan()
Dual(real=0.7854..., dual=0.5)
sinh()[source]

Compute the hyperbolic sine of the Dual number.

Returns

Hyperbolic sine of the original Dual number.

Return type

Dual

Examples

>>> x = Dual(1, 1)
>>> x.sinh()
Dual(real=1.1752..., dual=1.5431...)
cosh()[source]

Compute the hyperbolic cosine of the Dual number.

Returns

Hyperbolic cosine of the original Dual number.

Return type

Dual

Examples

>>> x = Dual(1, 1)
>>> x.cosh()
Dual(real=1.5431..., dual=1.1752...)
tanh()[source]

Compute the hyperbolic tangent of the Dual number.

Returns

Hyperbolic tangent of the original Dual number.

Return type

Dual

Examples

>>> x = Dual(1, 1)
>>> x.tanh()
Dual(real=0.7616..., dual=0.4200...)
sqrt()[source]

Compute the square root of the Dual number.

Returns

Square root of the original dual number.

Return type

Dual

Raises

ValueError – If the real part of dual number is negative.

Examples

>>> x = Dual(4, 1)
>>> x.sqrt()
Dual(real=2.0, dual=0.25)
>>> x = Dual(0, 1)
>>> x.sqrt()
Traceback (most recent call last):
    ...
ValueError: Square root is undefined when real parts of dual number are negetive.
pow(n)[source]

Compute the Dual number raised to a power n.

Parameters

n (float or int) – The power to which the Dual number is raised.

Returns

The original dual number raised to the given power.

Return type

Dual

Raises

TypeError – If n is not an int or float.

Examples

>>> x = Dual(2, 1)
>>> x.pow(3)
Dual(real=8.0, dual=12.0)

dual_autodiff.math_functions

dual_autodiff.autodiff_tools.sin(x)[source]

Compute the sin of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The sine of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import sin, Dual
  1. With a scalar input:
    >>> sin(0)
    0.0
    
  2. With a Dual number input:
    >>> sin(Dual(0, 1))
    Dual(real=0.0, dual=1.0)
    
  3. With a Dual numpy array input:
    >>> sin(np.array([Dual(2,3), Dual(3,4)]))
    array([Dual(real=0.9093..., dual=-1.2484...),
    Dual(real=0.1411..., dual=-3.9600...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.cos(x)[source]

Compute the cos of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The cosine of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import cos, Dual
  1. With a scalar input:
    >>> cos(0)
    1.0
    
  2. With a Dual number input:
    >>> cos(Dual(0, 1))
    Dual(real=1.0, dual=0.0)
    
  3. With a Dual numpy array input:
    >>> cos(np.array([Dual(2,3), Dual(3,4)]))
    array([Dual(real=-0.4161..., dual=-2.7278...),
    Dual(real=-0.9899..., dual=-0.1411...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.tan(x)[source]

Compute the tangent of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The tangent of the input.

Return type

float, Dual, or numpy.ndarray

Raises

ValueError – The tangent function is undefined as cosine of real part equals 0.

Examples

>>> from dual_autodiff import tan, Dual
  1. With a scalar input:
    >>> tan(0)
    0.0
    
  2. With a Dual number input:
    >>> tan(Dual(0, 1))
    Dual(real=0.0, dual=1.0)
    
  3. With a Dual numpy array input:
    >>> tan(np.array([Dual(2,3), Dual(3,4)]))
    array([Dual(real=-2.1850..., dual=5.7744...),
    Dual(real=-0.1425..., dual=16.2574...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.arcsin(x)[source]

Compute the arcsine of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The arcsine of the input.

Return type

float, Dual, or numpy.ndarray

Raises

ValueError – If a real part is outside the range [-1, 1].

Examples

>>> from dual_autodiff import arcsin, Dual
  1. With a scalar input:
    >>> arcsin(0)
    0.0
    
  2. With a Dual number input:
    >>> arcsin(Dual(0, 1))
    Dual(real=0.0, dual=1.0)
    
  3. With a Dual numpy array input:
    >>> arcsin(np.array([Dual(0.5,1), Dual(0.3,2)]))
    array([Dual(real=0.5235..., dual=1.1547...),
    Dual(real=0.3046..., dual=2.0910...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.arccos(x)[source]

Compute the arccosine of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Raises

ValueError – If the real part is outside the range [-1, 1].

Examples

>>> from dual_autodiff import arccos, Dual
  1. With a scalar input:
    >>> arccos(1)
    0.0
    
  2. With a Dual number input:
    >>> arccos(Dual(1, 1))
    Dual(real=0.0, dual=-1.0)
    
  3. With a Dual numpy array input:
    >>> arccos(np.array([Dual(0.5,1), Dual(0.3,2)]))
    array([Dual(real=1.0471..., dual=-1.1547...),
    Dual(real=1.2661..., dual=-2.0910...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.arctan(x)[source]

Compute the arctangent of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The arctangent of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import arctan, Dual
  1. With a scalar input:
    >>> arctan(1)
    0.7853981633974483
    
  2. With a Dual number input:
    >>> arctan(Dual(1, 1))
    Dual(real=0.7853981633974483, dual=0.5)
    
  3. With a Dual numpy array input:
    >>> arctan(np.array([Dual(1,1), Dual(0.5,2)]))
    array([Dual(real=0.7853..., dual=0.5),
    Dual(real=0.4636..., dual=1.6)],
    dtype=object)
    
dual_autodiff.autodiff_tools.sinh(x)[source]

Compute the hyperbolic sine of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The hyperbolic sine of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import sinh, Dual
  1. With a scalar input:
    >>> sinh(1)
    1.1752011936438014
    
  2. With a Dual number input:
    >>> sinh(Dual(1, 1))
    Dual(real=1.1752011936438014, dual=1.5430806348152437)
    
  3. With a Dual numpy array input:
    >>> sinh(np.array([Dual(1,1), Dual(0.5,2)]))
    array([Dual(real=1.1752..., dual=1.5430...),
    Dual(real=0.5210..., dual=2.1276...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.cosh(x)[source]

Compute the hyperbolic cosine of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The hyperbolic cosine of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import cosh, Dual
  1. With a scalar input:
    >>> cosh(1)
    1.5430806348152437
    
  2. With a Dual number input:
    >>> cosh(Dual(1, 1))
    Dual(real=1.5430806348152437, dual=1.1752011936438014)
    
  3. With a Dual numpy array input:
    >>> cosh(np.array([Dual(1,1), Dual(0.5,2)]))
    array([Dual(real=1.5430..., dual=1.1752...),
    Dual(real=1.1276..., dual=2.5210...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.tanh(x)[source]

Compute the hyperbolic tangent of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The hyperbolic tangent of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import tanh, Dual
  1. With a scalar input:
    >>> tanh(1)
    0.7615941559557649
    
  2. With a Dual number input:
    >>> tanh(Dual(1, 1))
    Dual(real=0.7615941559557649, dual=0.41997434161402614)
    
  3. With a Dual numpy array input:
    >>> tanh(np.array([Dual(1,1), Dual(0.5,2)]))
    array([Dual(real=0.7615..., dual=0.4199...),
    Dual(real=0.4621..., dual=1.7864...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.exp(x)[source]

Compute the exponential of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The exponential of the input.

Return type

float, Dual, or numpy.ndarray

Examples

>>> from dual_autodiff import exp, Dual
  1. With a scalar input:
    >>> exp(1)
    2.718281828459045
    
  2. With a Dual number input:
    >>> exp(Dual(1, 1))
    Dual(real=2.718281828459045, dual=2.718281828459045)
    
  3. With a Dual numpy array input:
    >>> exp(np.array([Dual(1,1), Dual(0.5,2)]))
    array([Dual(real=2.7182..., dual=2.7182...),
    Dual(real=1.6487..., dual=3.2974...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.log(x)[source]

Compute the natural logarithm of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The natural logarithm of the input.

Return type

float, Dual, or numpy.ndarray

Raises

ValueError – If a real part of dual number is non-positive

Examples

>>> from dual_autodiff import log, Dual
  1. With a scalar input:
    >>> log(1)
    0.0
    
  2. With a Dual number input:
    >>> log(Dual(1, 1))
    Dual(real=0.0, dual=1.0)
    
  3. With a Dual numpy array input:
    >>> log(np.array([Dual(1,1), Dual(2,2)]))
    array([Dual(real=0.0, dual=1.0),
    Dual(real=0.6931..., dual=1.0)],
    dtype=object)
    
dual_autodiff.autodiff_tools.sqrt(x)[source]

Compute the square root of a number, a Dual number, or a numpy array of Dual numbers.

Parameters

x (float, Dual, or numpy.ndarray) – The input value/values.

Returns

The square root of the input.

Return type

float, Dual, or numpy.ndarray

Raises

ValueError – If the real part of dual number is negative.

Examples

>>> from dual_autodiff import sqrt, Dual
  1. With a scalar input:
    >>> sqrt(4)
    2.0
    
  2. With a Dual number input:
    >>> sqrt(Dual(4, 1))
    Dual(real=2.0, dual=0.25)
    
  3. With a Dual numpy array input:
    >>> sqrt(np.array([Dual(4,1), Dual(9,2)]))
    array([Dual(real=2.0, dual=0.25),
    Dual(real=3.0, dual=0.3333...)],
    dtype=object)
    
dual_autodiff.autodiff_tools.pow(x, n)[source]

Compute a number, a Dual number, or a numpy array of Dual numbers raised to a power.

Parameters
  • x (float, Dual, or numpy.ndarray) – The base.

  • n (float) – The exponent.

Returns

The result of raising x to the power n.

Return type

float, Dual, or numpy.ndarray

Raises

TypeError – If n is not an int or float.

Examples

>>> from dual_autodiff import pow, Dual
  1. With a scalar input:
    >>> pow(2, 3)
    8
    
  2. With a Dual number input:
    >>> pow(Dual(2, 1), 3)
    Dual(real=8, dual=12.0)
    
  3. With a Dual numpy array input:
    >>> pow(np.array([Dual(2,1), Dual(3,2)]), 3)
    array([Dual(real=8, dual=12.0),
    Dual(real=27, dual=54.0)],
    dtype=object)
    
dual_autodiff.autodiff_tools.auto_diff(func, x)[source]

Evaluates the derivative of a function f at x using Dual number: x + ε.

Parameters
  • func (callable) – The function to differentiate.

  • x (float, int, or numpy.ndarray) – The point(s) where the derivative is evaluated.

Returns

A tuple containing the real and dual parts of the result.

If x is a scalar, returns (real, dual). If x is a numpy array, returns two numpy arrays (real_array, dual_array).

Return type

tuple

Raises
  • TypeError – If func is not callable.

  • TypeError – If input x is not a float, int, or numpy.ndarray containing scalar values.

Examples

>>> from dual_autodiff import auto_diff
  1. With a scalar input:
    >>> auto_diff(lambda x: x**3 + 2*x**2 + x, 2)
    (14.0, 17.0)
    
  2. With a numpy array input:
    >>> auto_diff(lambda x: x**3 + 2*x**2 + x, np.array([1, 2, 3]))
    (array([ 4.0, 14.0, 34.0]), array([ 4.0, 17.0, 40.0]))
    
dual_autodiff.autodiff_tools.multi_auto_diff(funcs, x)[source]

Evaluates the derivatives of multiple functions at x using Dual number: x + ε.

Parameters
  • funcs (list of callables) – The functions to differentiate.

  • x (float, int, or numpy.ndarray) – The point(s) where the derivatives are evaluated.

Returns

A list of tuples, each containing the real and dual parts of the result for each function.

If x is a scalar, each tuple is (real, dual). If x is a numpy array, each tuple contains two numpy arrays (real_array, dual_array).

Return type

list of tuples

Raises
  • TypeError – If any func in funcs is not callable.

  • TypeError – If input x is not a float, int, or numpy.ndarray containing scalar values.

Examples

>>> from dual_autodiff import multi_auto_diff
  1. With a scalar input:
    >>> multi_auto_diff([lambda x: x**3, lambda x: x**2], 2)
    [(8.0, 12.0), (4.0, 4.0)]
    
  2. With a numpy array input:
    >>> multi_auto_diff([lambda x: x**3, lambda x: x**2], np.array([1, 2, 3]))
    [(array([ 1.0,  8.0, 27.0]), array([ 3.0, 12.0, 27.0])), (array([1.0, 4.0, 9.0]), array([2.0, 4.0, 6.0]))]