Skip to main content

Exact limit computation for Python functions. Resolve singularities algebraically.

Project description

composite-resolve

Evaluate Python functions at points where they're undefined.

The library where you pass a plain numeric Python function and get exact limits via algebraic infinitesimal arithmetic, with provenance tracking. To my knowledge, this is the first library that does this directly on plain Python functions.

Eliminates edge-case handling and numerical instability at singularities — just write the function and evaluate it everywhere.

import math
from composite_resolve import safe

@safe
def sinc(x):
    return math.sin(x) / x

sinc(0.5)  # → 0.9589 (normal computation)
sinc(0)    # → 1.0 (singularity resolved)

Uses composite arithmetic to resolve singularities algebraically. Works with any callable that uses standard Python arithmetic and math module functions. No symbolic expressions, no approximation. Pure Python, zero dependencies.

Install

pip install composite-resolve

The @safe Decorator

Write your math as-is. The decorator handles singularities automatically:

import math
from composite_resolve import safe

@safe
def f(x):
    return (x**2 - 1) / (x - 1)

f(3)   # → 4.0 (normal)
f(1)   # → 2.0 (resolved — no ZeroDivisionError)

@safe
def entropy(p):
    return -p * math.log(p)

entropy(0.5)  # → 0.347 (normal)
entropy(0)    # → 0.0 (resolved — no ValueError)

Normal inputs run the original function directly with zero overhead. Only when the function fails (ZeroDivisionError, NaN, Inf) does the resolver kick in.

Direct API

For more control, use resolve, limit, and classify directly:

import math
from composite_resolve import resolve, limit, classify, taylor

# Evaluate at removable singularities
resolve(lambda x: math.sin(x) / x, at=0)                # → 1.0
resolve(lambda x: (math.exp(x) - 1) / x, at=0)          # → 1.0
resolve(lambda x: (x**2 - 1) / (x - 1), at=1)           # → 2.0

# Indeterminate forms
limit(lambda x: x * math.log(x), to=0, dir="+")          # → 0.0    (0 * inf)
limit(lambda x: x**x, to=0, dir="+")                      # → 1.0    (0^0)
limit(lambda x: (1 + x)**(1/x), to=0)                     # → e      (1^inf)
limit(lambda x: 1/x - 1/math.sin(x), to=0)                # → 0.0    (inf - inf)

# Limits at infinity
limit(lambda x: (1 + 1/x)**x, to=math.inf)                # → e
limit(lambda x: math.sin(x) / x, to=math.inf)              # → 0.0

# One-sided limits
limit(lambda x: 1/x, to=0, dir="+")   # raises LimitDivergesError (+inf)
limit(lambda x: 1/x, to=0, dir="-")   # raises LimitDivergesError (-inf)
limit(lambda x: 1/x, to=0)            # raises LimitDoesNotExistError

# Singularity classification
classify(lambda x: math.sin(x)/x, at=0)   # → Removable(value=1.0)
classify(lambda x: 1/x, at=0)             # → Pole(order=1, residue=1.0)
classify(lambda x: math.exp(x), at=0)     # → Regular(value=1.0)

# Taylor coefficients
taylor(lambda x: math.exp(x), at=0, order=4)
# → [1.0, 1.0, 0.5, 0.16667, 0.04167]

How It Works

The library evaluates functions using composite arithmetic. Instead of symbolic manipulation, the library substitutes a concrete algebraic infinitesimal into your function. The result carries enough structure to resolve 0/0, 0×∞, and all other indeterminate forms through ordinary arithmetic.

The function is treated as a black box. No expression tree, no symbolic manipulation.

The function is treated as a black box. No expression tree, no symbolic manipulation.

API

safe(f) -> wrapped function

Decorator. Normal inputs run f directly. Singularities are resolved automatically.

resolve(f, at, dir="both", truncation=20) -> float

Evaluate f at a point where it would normally fail. Returns math.inf or -math.inf for divergent limits.

limit(f, to, dir="both", truncation=20) -> float

Compute the limit of f(x) as x -> to. Raises LimitDivergesError for infinite limits, LimitDoesNotExistError when the limit doesn't exist.

evaluate(f, at) -> float

Strict: only returns a value if the singularity is removable. Raises SingularityError otherwise.

taylor(f, at=0, order=10) -> list[float]

Extract Taylor coefficients [f(a), f'(a)/1!, f''(a)/2!, ...].

classify(f, at=0, dir="both") -> SingularityType

Returns Regular, Removable, Pole, or Essential.

residue(f, at=0) -> float

Residue at a pole.

Examples

# Evaluate a function across its full domain, including singularities
from composite_resolve import resolve

f = lambda x: (x**2 - 1) / (x - 1)
for x in range(-5, 6):
    print(f"x={x:>2d}  f(x)={resolve(f, at=x):.1f}")
# x=1 gives 2.0 — no special case needed
# Cross-entropy loss at boundary
resolve(lambda p: -(0*math.log(p) + 1*math.log(1-p)), at=0, dir="+")  # → 0.0

# Continuous compounding
limit(lambda n: (1 + 0.05/n)**n, to=math.inf)  # → 1.05127

Math Library Support

Functions can use math, numpy, or composite_resolve.math — all work transparently:

import math
import numpy as np
from composite_resolve import safe

@safe
def f(x):
    return math.sin(x) / x    # works

@safe
def g(x):
    return np.sin(x) / x      # also works

f(0)  # → 1.0
g(0)  # → 1.0

math functions are patched during resolution. numpy functions dispatch via __array_ufunc__.

Limitations

  • Single-variable functions only
  • Functions must use math or numpy transcendentals (not jax, torch, etc.)
  • Not thread-safe during limit()/resolve()/@safe calls
  • Float-precision evaluation points (e.g., math.pi/2 is not exactly pi/2)

License

AGPL-3.0. Commercial licensing available: tmilovan@fwd.hr

Author

Toni Milovan — tmilovan@fwd.hr

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

composite_resolve-0.1.1.tar.gz (32.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

composite_resolve-0.1.1-py3-none-any.whl (42.2 kB view details)

Uploaded Python 3

File details

Details for the file composite_resolve-0.1.1.tar.gz.

File metadata

  • Download URL: composite_resolve-0.1.1.tar.gz
  • Upload date:
  • Size: 32.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for composite_resolve-0.1.1.tar.gz
Algorithm Hash digest
SHA256 65396f0c39eb715dfba468ffee3fe0c016236d785ea9997d15082b5eca22d985
MD5 bdebdd2ca51839ea152339db132c6b34
BLAKE2b-256 c7d987125f644b0c71d4326f9d6c9523fd0414ff2a494186c186ce80cf731f13

See more details on using hashes here.

File details

Details for the file composite_resolve-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for composite_resolve-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 63752d88493033c189c1c120b7ad039007dc4371c40f18111441d698ba76dc2e
MD5 d91c6e37ac422aebee1663bcd04b61a2
BLAKE2b-256 b927431a137f1e9370ef1a2619a617c9b541c2932a60c3f73ece470d5a6fa5fd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page