Apart¶
Status: Stable
documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
Description¶
Apart[expr]
rewrites a rational expression as a sum of terms with minimal denominators.
Apart[expr, var]
treats all variables other than var as constants.
Notes
Option Extension -\> alpha factors the denominator over Q(alpha) before decomposition, splitting (x^2 - 2) into (x - Sqrt\[2\])(x + Sqrt\[2\]) under Extension -\> Sqrt\[2\] and producing the corresponding linear-factor partial fractions. Default Extension -\> None decomposes over Q.Examples (12)¶
Every input below was run against the current Mathilda build and its output recorded.
Basic examples (5)¶
In[1]:= Apart[1/((1+x)(5+x))]
Out[1]= -1/(4 (5 + x)) + 1/(4 (1 + x))
In[2]:= Apart[(x^5-2)/((1+x+x^2)(2+x)(1-x))]
Out[2]= 2 - x - 34/(9 (2 + x)) + 1/(9 (-1 + x)) + (-1 - 1/3 x)/(1 + x + x^2)
In[3]:= Apart[(x+y)/((x+1)(y+1)(x-y)), x]
Out[3]= -(-1 + y)/((1 + x) (1 + y)^2) + (2 y)/((1 + y)^2 (x - y))
In[4]:= Apart[1/(y^(2/3) - 1/y^(1/3))]
Out[4]= 1/(3 (-1 + y^(1/3))) + (1/3 - 1/3 y^(1/3))/(1 + y^(1/3) + y^(2/3))
In[5]:= Apart[1/((Sqrt[x] + 2) (Sqrt[x] + 3)), x]
Out[5]= 1/(2 + Sqrt[x]) - 1/(3 + Sqrt[x])
Options (1)¶
In[6]:= Apart[1/(x^2 - 2), x, Extension -> Sqrt[2]]
Out[6]= -1/(2 Sqrt[2] (Sqrt[2] + x)) + 1/(2 Sqrt[2] (-Sqrt[2] + x))
Applications (6)¶
In[7]:= Apart[1/(x (x+1))]
Out[7]= 1/x - 1/(1 + x)
In[8]:= Apart[(x+2)/(x^2 - 1)]
Out[8]= -1/(2 (1 + x)) + 3/(2 (-1 + x))
In[9]:= Apart[1/(x^2 (x+1))]
Out[9]= 1/x^2 - 1/x + 1/(1 + x)
In[10]:= Apart[(x^3 + 1)/(x^2 - 1)]
Out[10]= x + 1/(-1 + x)
In[11]:= Apart[(2 x + 3)/((x+1)^2 (x^2+1))]
Out[11]= 1/(2 (1 + x)^2) + 3/(2 (1 + x)) + (1 - 3/2 x)/(1 + x^2)
In[12]:= Apart[1/(x^2 - 2), Extension -> Sqrt[2]]
Out[12]= -1/(2 Sqrt[2] (Sqrt[2] + x)) + 1/(2 Sqrt[2] (-Sqrt[2] + x))
Implementation notes¶
Algorithm. builtin_apart strips an optional Extension -> α (with Automatic running extension_autodetect for a single algebraic generator) and dispatches to apart_impl. Inexact coefficients route through internal_rationalize_then_numericalize. The core does an undetermined-coefficients partial-fraction decomposition over Q (or Q(α)):
- Thread over
List/relational/logical heads when the argument is one. - For a radical generator (fractional rational exponents), substitute
u -> g^m, recurse, and back-substitute (poly_find_radical_gen/poly_subst_radical_*). - Combine to a single fraction with
Together, pick the partial-fraction variable (explicit 2nd arg, else the lexicographically-last collected variable), and split into numeratorNand denominatorD(bailing back to theTogether'd form if either is not polynomial in the variable, checked byPolynomialQ). - Polynomial-divide
NbyD(PolynomialQuotient/PolynomialRemainder) to get the polynomial partQand proper remainderR. Factorthe denominator (over the extension if given), separate constant factors into a scalarC, and for each irreducible baseb_iof multiplicityk_iset up unknown numerators of degreedeg(b_i)-1over each powerb_i^j.- Build the linear system by expanding each basis-times-
var^rterm, reading coefficients withget_coeff, and solving viaRowReduce; assemble the sumQ + sum A_ij / b_i^j, factoring each solved coefficient.
Data structures. Everything is Expr trees driven through eval_and_free/expr_expand. The linear system is a dense Expr*** augmented matrix (S rows by S+1 columns, S = deg(D)) of coefficient expressions handed to RowReduce; factored denominator bases and their exponents are kept in parallel Expr**/int64* arrays.
Complexity / limits. Dominated by Factor[D] and the O(S^3) RowReduce over symbolic entries. Partial fractions are undefined when N/D are not polynomial in the chosen variable (handled by returning the combined fraction), and the matrix path assumes integer/rational coefficient structure.
Protected,Listable.- Writes
expras a polynomial invartogether with a sum of ratios of polynomials with minimal denominators. - If
varis not specified, intelligently selects the main polynomial variable natively. - Algebraic-generator substitution. When the input is a rational function of a radical or fractional power
g = u^(1/m)(e.g.Sqrt[x],y^(1/3)), the decomposition happens ing: the generator is substituted for a fresh symbol,Apartruns in that symbol, thengis back-substituted — soApart[1/((Sqrt[x]+2)(Sqrt[x]+3))]gives1/(2+Sqrt[x]) - 1/(3+Sqrt[x]). The explicit two-argument form applies this too, but only when the radical is a genuine radical ofvaritself (Apart[f[Sqrt[x]], x]); a radical of any other symbol is left as an opaque constant invar. - Implements exact undetermined coefficients algebraically leveraging row-reduced identity expansions over algebraic inputs avoiding recursive fractional losses natively.
- Fast path (plain rationals over Q). When
varis a symbol and every coefficient is rational (no other symbol / radical / fractional power), the decomposition runs natively in FLINTfmpq_poly(flint_apart_over_q): a distinct-factor CRT split (xgcd) followed by ap_i-adic expansion, replacing theO(S^2+)symbolicRowReduce. High-degree denominators drop from tens of seconds to sub-second (Apart[(x-99)/((x+2)^60 (x-3)^40), x]: ~15.6 s → ~0.74 s). The multivariate / algebraic case declines to the classical elimination path, so output is unchanged. - When
Together[expr]produces a numerator or denominator that is not polynomial in the chosen variable and no algebraic-generator substitution applies (e.g. fractional-power inputs whose Together'd form isy^(1/3)/(y - 1)), the matrix-of-coefficients algorithm cannot apply; Apart returns theTogetherform unchanged rather than synthesising a spurious zero. - Option
Extension -> alpha(Phase 0 of the Integrate plan) factors the denominator overQ(alpha)before partial-fraction decomposition runs, splitting reducible-over-extension factors (e.g.x^2 - 2into(x - Sqrt[2])(x + Sqrt[2])underExtension -> Sqrt[2]) and producing the corresponding linear-factor partial fractions. The pre-Togetherstep is also extension-aware so any algebraic-number cancellations in numerator/denominator fire before splitting.
Attributes: Listable, Protected.
References¶
- Geddes, Czapor & Labahn, "Algorithms for Computer Algebra" (1992), on partial fraction decomposition.
- von zur Gathen & Gerhard, "Modern Computer Algebra", on partial fractions and the extended Euclidean algorithm.
- K. O. Geddes, S. R. Czapor and G. Labahn, Algorithms for Computer Algebra (Kluwer, 1992), ch. on partial-fraction decomposition.
- Source:
src/parfrac.c - Specification:
docs/spec/builtins/algebra.md - Tests:
tests/test_eval_timestamps.c - Tests:
tests/test_expr_sharing.c - Tests:
tests/test_extension_auto_builtins.c - Tests:
tests/test_extension_options.c
Notes & additional examples¶
Notes¶
Apart computes the partial-fraction decomposition with respect to the (sole)
variable, the inverse of Together. It factors the denominator and splits the
quotient into a sum of terms whose denominators are the factors, including
repeated-factor terms: 1/(x^2 (x+1)) decomposes into 1/x^2 - 1/x + 1/(1+x),
recovering both the 1/x^2 and the lower-order 1/x contributions. Rational
residues appear when the factors are linear over the rationals, as in the
-1/2 and 3/2 coefficients for (x+2)/(x^2-1). When the numerator degree
meets or exceeds the denominator's, Apart first divides out a polynomial part:
(x^3 + 1)/(x^2 - 1) becomes x + 1/(-1 + x). Irreducible quadratic factors
over Q are kept intact (the (1 - 3/2 x)/(1 + x^2) term), while
Extension -> Sqrt[2] splits x^2 - 2 into the conjugate linear factors
x +- Sqrt[2] and produces the corresponding partial fractions over
Q(Sqrt[2]).