limcalc: Limit-based symbolic calculus engine via log-Puiseux series

[ library, math, mit, program ] [ Propose Tags ] [ Report a vulnerability ]

limcalc is a symbolic calculus engine grounded in the limit definition rather than rewriting rules. The core thesis: the derivative is a limit, so compute it that way — expand f(x+h) as a log-Puiseux series in h and read off the h^1 coefficient. The product rule and chain rule are not implemented; both are consequences of the limit definition and are observable in the output. . The log-Puiseux series type supports terms of the form c * h^p * log(h)^k with c an algebraic number, p rational, and k a natural number. This is strictly more expressive than pure Puiseux series: the cosine integral Ci and exponential integral Ei have genuine logarithmic singularities that cannot be represented as pure power series. . Capabilities: . * Univariate and multivariate limits with certified result types (Exists, Pole, DoesNotExist, LimitError) . * Symbolic differentiation — gradient, Jacobian, Hessian — derived from the same log-Puiseux representation, without rule tables . * Integration via the Risch algorithm over the differential field the representation naturally provides, with NonElementary as a proved certificate when no elementary antiderivative exists . * Recognition of non-elementary integrals as named special functions: erf, Si, Ci, Ei, li . * JSON line protocol CLI (limcalc-cli) for language-agnostic use; a Python interface is available as the limcalc-py package on PyPI


[Skip to Readme]

Modules

  • LimCalc
    • Algebra
      • LimCalc.Algebra.AlgNum
      • LimCalc.Algebra.BivPoly
      • LimCalc.Algebra.Poly
      • LimCalc.Algebra.QPoly
      • LimCalc.Algebra.RationalFunction
    • Core
      • LimCalc.Core.Expr
      • LimCalc.Core.ExprJSON
      • LimCalc.Core.Simplify
      • LimCalc.Core.Types
    • Differentiation
      • LimCalc.Differentiation.Calculus
      • LimCalc.Differentiation.DiffField
      • LimCalc.Differentiation.Limit
      • LimCalc.Differentiation.MultivariateLimit
    • Integration
      • LimCalc.Integration.Risch
        • LimCalc.Integration.Risch.Exponential
        • LimCalc.Integration.Risch.Primitive
    • LimCalc.Pretty
    • Series
      • LimCalc.Series.Expand
      • LimCalc.Series.Puiseux
      • LimCalc.Series.SymExpand
      • LimCalc.Series.SymPuiseux

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0
Change log CHANGELOG.md
Dependencies aeson (>=2.3.0 && <2.4), base (>=4.20.2.0 && <4.21), bytestring (>=0.12.2 && <0.13), containers (>=0.7 && <0.8), limcalc [details]
Tested with ghc ==9.10.3
License MIT
Copyright 2026 Jason Parker
Author Jason Parker
Maintainer jparker588@gmail.com
Uploaded by penny4nonsense at 2026-07-07T18:45:43Z
Category Math
Home page https://github.com/penny4nonsense/limcalc
Bug tracker https://github.com/penny4nonsense/limcalc/issues
Distributions
Executables limcalc-cli
Downloads 1 total (1 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs not available [build log]
All reported builds failed as of 2026-07-07 [all 2 reports]

Readme for limcalc-0.1.0.0

[back to package description]

limcalc

A symbolic calculus engine built on the limit definition rather than rewriting rules.

Differentiation, integration, and limit evaluation are all derived from a single underlying representation — the log-Puiseux series — finite formal sums of terms c · hᵖ · log(h)ᵏ with c an algebraic number, p rational, and k a natural number. The derivative is the coefficient of in the expansion of f(x+h). The product rule and chain rule are not implemented; both are consequences of the limit definition and are observable in the output.

Quick start

import LimCalc.Core.Expr
import LimCalc.Differentiation.Calculus
import LimCalc.Differentiation.Limit
import LimCalc.Integration.Risch

-- Symbolic expressions
let f = Sin (Var "x")

-- Symbolic differentiation
diff f "x"
-- Right (Cos (Var "x"))

-- Gradient
gradient (Add (Pow (Var "x") (Lit 2)) (Pow (Var "y") (Lit 2))) ["x", "y"]
-- Right [Mul (Lit 2) (Var "x"), Mul (Lit 2) (Var "y")]

-- Limits
limit (Div (Sin (Var "x")) (Var "x")) "x" 0.0
-- Exists 1.0

limit (Div (Lit 1) (Var "x")) "x" 0.0
-- Pole (-1.0)

-- Integration
rischIntegrate (Sin (Var "x")) "x"
-- Elementary (Neg (Cos (Var "x")))

rischIntegrate (Exp (Neg (Pow (Var "x") (Lit 2)))) "x"
-- SpecialFunction (Mul (Div (Sqrt Pi) (Lit 2)) (Erf (Var "x")))

rischIntegrate (Exp (Pow (Var "x") (Lit 2))) "x"
-- NonElementary

API

Differentiation

-- Symbolic derivative (algebraic path)
diff :: Expr -> String -> Either ExpandError Expr

-- Partial derivative
partialDiff :: Expr -> String -> Either ExpandError Expr

-- Gradient, Jacobian, Hessian
gradient :: Expr -> [String] -> Either ExpandError [Expr]
jacobian :: [Expr] -> [String] -> Either ExpandError [[Expr]]
hessian  :: Expr -> [String] -> Either ExpandError [[Expr]]

-- Numeric derivative at a point
derivative    :: Expr -> Map String Double -> String -> Either ExpandError Double
partial       :: Expr -> Map String Double -> String -> Either ExpandError Double
nthDerivative :: Int -> Expr -> Map String Double -> String -> Either ExpandError Double

Limits

-- One-sided and two-sided limits
limit      :: Expr -> String -> Double -> LimitResult Double
limitRight :: Expr -> String -> Double -> LimitResult Double
limitLeft  :: Expr -> String -> Double -> LimitResult Double

LimitResult is a certified result type:

data LimitResult a
  = Exists a            -- limit exists and equals a
  | Pole Double         -- diverges; leading log-Puiseux exponent
  | DoesNotExist String -- certified non-existence with witness
  | LimitError String   -- outside the representation class

Integration

rischIntegrate :: Expr -> String -> RischResult

RischResult distinguishes proved outcomes:

data RischResult
  = Elementary Expr       -- elementary antiderivative
  | SpecialFunction Expr  -- named special function (erf, Si, Ci, Ei, li)
  | NonElementary         -- proved: no elementary antiderivative exists

NonElementary is a mathematical certificate, not a failure. It is returned only when the Risch algorithm has determined non-existence via Liouville's theorem — never on timeout or truncation.

Supported special functions

The following non-elementary integrals are recognized and returned as named constructors:

Integrand Result
exp(-x²) (√π/2) · erf(x)
sin(x)/x Si(x)
cos(x)/x Ci(x)
exp(x)/x Ei(x)
1/log(x) li(x)

CLI

The package includes limcalc-cli, a JSON line protocol server suitable for use from other languages:

$ limcalc-cli
{"op":"diff","expr":{"tag":"Sin","arg":{"tag":"Var","name":"x"}},"var":"x"}
{"ok":true,"result":{"tag":"Cos","arg":{"tag":"Var","name":"x"}}}
{"op":"limit","expr":{"tag":"Div","left":{"tag":"Sin","arg":{"tag":"Var","name":"x"}},"right":{"tag":"Var","name":"x"}},"var":"x","x0":0}
{"ok":true,"result":1.0}

A Python interface wrapping this CLI is available as limcalc-py on PyPI.

Background

The log-Puiseux type is strictly more expressive than pure Puiseux series. The cosine integral Ci(x) near x = 0 expands as γ + log(h) - h²/4 + ⋯ — the log(h) term cannot be represented as a finite sum of powers hᵖ. The system proves this formally (Lemma 2.1 in the paper) and uses it to motivate the representation class.

The boundary of the class is sharp: li(x) = Ei(log x) near x = 0 requires log(log(h)) terms, which lie outside the single-logarithm tower. The system correctly computes d/dx li(x) = 1/log(x) via the algebraic path while returning LimitError for the series path — an honest boundary, not an error.

License

MIT