Skip to main content

A from-scratch Python library for symbolic and numerical calculus operations

Project description

Calcus

PyPI version Python versions License: MIT Tests

A lightweight, dependency-free Python library for symbolic and numerical calculus operations.

Why Calcus?

  • Zero dependencies — no SymPy, NumPy, or any external math library required
  • Educational — transparent implementation of calculus algorithms you can study and modify
  • Simple API — intuitive functions that do exactly what you expect
  • Lightweight — no heavy symbolic engine overhead, fast imports, minimal footprint
  • Both symbolic and numerical — get exact answers when possible, approximations when needed

Installation

From PyPI

pip install calcus

From source

git clone https://github.com/nalqit/calcus.git
cd calcus
pip install -e .

Development install (with pytest)

pip install -e ".[dev]"

Quick Start

from calcus import parse, differentiate, integrate, limit, pretty

# Parse an expression from a string
expr = parse("x^2 + sin(x)")

# Differentiate
diff_result = differentiate(expr, "x")
print(pretty(diff_result))  # 2 * x + cos(x)

# Integrate
int_result = integrate(expr, "x")
print(pretty(int_result))  # x ^ 3 / 3 - cos(x)

# Limits
lim = limit(parse("sin(x)/x"), "x", 0)
print(lim)  # 1.0

CLI Usage

Calcus ships with a command-line interface:

# Symbolic differentiation
calcus --diff "x^2 + sin(x)" --var x

# Symbolic integration
calcus --integrate "sin(x)" --var x

# Limits
calcus --limit "sin(x)/x" --var x --point 0

# Taylor series
calcus --taylor "exp(x)" --var x --order 5

# Numerical integration
calcus --num-int "x^2" --var x --lower 0 --upper 1

# LaTeX output
calcus --diff "x^3" --var x --latex

# Interactive REPL
calcus --repl

API Reference

Parsing

from calcus import parse

expr = parse("x^2 + 2*x + 1")        # Addition and multiplication
expr = parse("sin(x) * cos(x)")      # Functions
expr = parse("exp(x) / x^2")         # Division and powers
expr = parse("sqrt(x) + ln(x)")      # Square root, natural log
expr = parse("atan(x^2)")            # Inverse trig functions

Supported functions: sin, cos, tan, sec, csc, cot, asin/arcsin, acos/arccos, atan/arctan, exp, ln/log, sqrt, abs

Symbolic Differentiation

from calcus import parse, differentiate, gradient, hessian

# Basic derivatives
differentiate(parse("x^3"), "x")               # 3 * x ^ 2
differentiate(parse("sin(x)"), "x")            # cos(x)
differentiate(parse("exp(x)"), "x")            # exp(x)
differentiate(parse("ln(x)"), "x")             # 1 / x

# Higher-order derivatives
differentiate(parse("x^4"), "x", order=2)      # 12 * x ^ 2
differentiate(parse("sin(x)"), "x", order=3)   # -cos(x)

# Chain rule
differentiate(parse("sin(x^2)"), "x")          # 2 * x * cos(x ^ 2)

# Product rule
differentiate(parse("x * sin(x)"), "x")        # sin(x) + x * cos(x)

# Quotient rule
differentiate(parse("sin(x) / x"), "x")        # (x * cos(x) - sin(x)) / x ^ 2

# Multivariable
expr = parse("x^2 * y + y^3")
gradient(expr, ["x", "y"])                     # [2 * x * y, x ^ 2 + 3 * y ^ 2]
hessian(expr, ["x", "y"])                      # [[2 * y, 2 * x], [2 * x, 6 * y]]

Symbolic Integration

from calcus import parse, integrate, definite_integral

# Basic antiderivatives
integrate(parse("x^2"), "x")                   # x ^ 3 / 3
integrate(parse("sin(x)"), "x")                # -cos(x)
integrate(parse("cos(x)"), "x")                # sin(x)
integrate(parse("exp(x)"), "x")                # exp(x)
integrate(parse("1/x"), "x")                   # ln(x)

# Definite integrals
definite_integral(parse("x^2"), "x", 0, 1)     # 0.33333...
definite_integral(parse("sin(x)"), "x", 0, 3.14159)  # ~2.0

Limits

from calcus import parse, limit

# Direct substitution
limit(parse("x^2 + 1"), "x", 3)                # 10.0

# 0/0 indeterminate form (L'Hôpital's rule)
limit(parse("sin(x)/x"), "x", 0)               # 1.0

# Limits at infinity
limit(parse("1/x"), "x", "inf")                # 0.0
limit(parse("1/x"), "x", "-inf")               # 0.0

Numerical Differentiation

from calcus import parse, numerical_diff, numerical_diff2

expr = parse("x^2")
numerical_diff(expr, "x", 2)                   # ~4.0
numerical_diff2(expr, "x", 2)                  # ~2.0

# Choose method: 'forward', 'backward', 'central' (default)
numerical_diff(expr, "x", 2, method="central")

Numerical Integration

from calcus import parse, trapezoidal_rule, simpsons_rule, adaptive_quadrature, gaussian_quadrature

expr = parse("x^2")

trapezoidal_rule(expr, "x", 0, 1, n=1000)      # ~0.333
simpsons_rule(expr, "x", 0, 1, n=100)          # ~0.333
adaptive_quadrature(expr, "x", 0, 1)           # ~0.333 (high precision)
gaussian_quadrature(expr, "x", 0, 1, n=3)      # ~0.333

Taylor & Maclaurin Series

from calcus import parse, taylor_series, maclaurin_series, pretty

# Maclaurin series (Taylor at x=0)
series = maclaurin_series(parse("exp(x)"), "x", order=5)
print(pretty(series))  # 1 + x + x^2/2 + x^3/6 + x^4/24

series = maclaurin_series(parse("sin(x)"), "x", order=6)
print(pretty(series))  # x - x^3/6 + x^5/120

# Taylor series at arbitrary point
series = taylor_series(parse("ln(x)"), "x", point=1, order=4)

Vector Calculus

from calcus import parse, gradient, divergence, curl, laplacian

# Gradient of scalar field
f = parse("x^2 + y^2 + z^2")
gradient(f, ["x", "y", "z"])                  # [2*x, 2*y, 2*z]

# Divergence of vector field
F = [parse("x^2"), parse("y^2"), parse("z^2")]
divergence(F, ["x", "y", "z"])                # 2*x + 2*y + 2*z

# Curl of vector field
curl(F, ["x", "y", "z"])                      # [0, 0, 0]

# Laplacian
laplacian(f, ["x", "y", "z"])                 # 6

ODE Solvers

from calcus import ODESolver

# dy/dx = y, y(0) = 1  (solution: y = e^x)
def f(x, y):
    return y

result = ODESolver.runge_kutta_4(f, y0=1, x0=0, x_end=1, h=0.1)
for x, y in result:
    print(f"y({x:.1f}) = {y:.6f}")

Pretty Printing

from calcus import parse, pretty, to_latex

expr = parse("x^2 + 2*x + 1")
print(pretty(expr))     # x ^ 2 + 2 * x + 1
print(to_latex(expr))   # x^{2} + 2 \cdot x + 1

Expression API

from calcus import parse, constant, symbol

# Create expressions programmatically
x = symbol("x")
expr = x ** 2 + 2 * x + 1

# Evaluate with variable bindings
expr = parse("x^2 + 3*x + 2")
expr.evaluate({"x": 2})                     # 12.0

# Substitute variables
expr.substitute("x", constant(3))           # x^2 + 3*x + 2 with x=3
expr.substitute("x", parse("y+1"))          # Replace x with (y+1)

# Get all variables in an expression
parse("x^2 + sin(y)").symbols()             # {"x", "y"}

Complex Example

from calcus import parse, differentiate, integrate, maclaurin_series, pretty

# Differentiate a complex expression
expr = parse("exp(x) * sin(x^2) / (1 + x^2)")
deriv = differentiate(expr, "x")
print(pretty(deriv))

# Expand sin(x) as a Maclaurin series
series = maclaurin_series(parse("sin(x)"), "x", order=8)
print(pretty(series))
# x - x^3 / 6 + x^5 / 120 - x^7 / 5040

Project Structure

calcus/
├── calcus/
│   ├── __init__.py          # Public API exports
│   ├── __main__.py          # CLI entry point
│   ├── core/
│   │   ├── expression.py    # Expression AST nodes
│   │   ├── parser.py        # Recursive descent parser
│   │   ├── simplify.py      # Expression simplification
│   │   └── pretty.py        # ASCII and LaTeX formatting
│   ├── symbolic/
│   │   ├── differentiate.py # Symbolic differentiation
│   │   ├── integrate.py     # Symbolic integration
│   │   └── limits.py        # Limit computation
│   ├── numerical/
│   │   ├── differentiate.py # Numerical differentiation
│   │   └── integrate.py     # Numerical integration
│   └── advanced/
│       ├── series.py        # Taylor/Maclaurin series
│       ├── ode.py           # ODE solvers
│       └── vector.py        # Vector calculus
├── tests/
│   └── test_calculus.py     # All tests
├── pyproject.toml
├── README.md
└── LICENSE

Limitations

  • No implicit multiplication: Write 2*x not 2x
  • Integration is rule-based: Handles common cases but not a full CAS like SymPy. Complex integrals may raise NotImplementedError
  • Simplification is basic: Does not apply trig identities, log rules, or polynomial factoring
  • Single variable focus: Multivariable support exists for gradient/Hessian/divergence/curl but not for limits or integration
  • No complex numbers: All operations are over real numbers

Running Tests

pip install -e ".[dev]"
pytest tests/ -v
pytest tests/ -v --cov=calcus

License

MIT

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

calcus-0.1.1.tar.gz (31.8 kB view details)

Uploaded Source

Built Distribution

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

calcus-0.1.1-py3-none-any.whl (31.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for calcus-0.1.1.tar.gz
Algorithm Hash digest
SHA256 586779aff232c81b784daff8ab8d4de304a0d1109a39b46a1951eed7a5ecf9f5
MD5 562192b8a6a2822edba1f6318d4d7edd
BLAKE2b-256 33b234e2d60e2cace61385253234484842f55eaa78fb6fc4256fc007d4030ca5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: calcus-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 31.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for calcus-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 db0fa081bc1ccba758150e64404655a76bc7ce327143b74b64892bbbea095901
MD5 5e028e016180cd9abee7e842cc6b4133
BLAKE2b-256 15b5bc36f2b82df9a3d3fc6aa8a7d97a294d452f82044e99c38ca0aea841e8a1

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