Skip to content

Together

Status: Stable

documented, exercised by the test suite and/or worked examples, with no known limitations recorded.

Description

Together[expr]

combines fractions over a common denominator, then cancels.

Notes Option Extension -\> alpha runs the final cancellation over Q(alpha) so algebraic-coefficient simplifications fire (e.g. 1/(x-Sqrt\[2\]) + 1/(x+Sqrt\[2\]) collapses to (2 x)/(x^2 - 2) under Extension -\> Sqrt\[2\]). Default Extension -\> None combines and cancels over the rationals only.

Examples (16)

Every input below was run against the current Mathilda build and its output recorded.

Basic examples (6)

In[1]:= Together[a/b + c/d]
Out[1]= (b c + a d)/(b d)

In[2]:= Together[x^2/(x^2 - 1) + x/(x^2 - 1)]
Out[2]= x/(-1 + x)

In[3]:= Together[1/x + 1/(x + 1) + 1/(x + 2) + 1/(x + 3)]
Out[3]= (6 + 22 x + 18 x^2 + 4 x^3)/(6 x + 11 x^2 + 6 x^3 + x^4)

In[4]:= Together[x^2/(x - y) - x y/(x - y)]
Out[4]= x

In[5]:= Together[y^(5/8)*(y^(19/8) - y^(73/24)/(y^(2/3) - 1/y^(1/3)))]
Out[5]= -y^3/(-1 + y)

In[6]:= Together[1/(x - k^(1/3)) + 1/(x + k^(1/3))]
Out[6]= -(2 x)/(k^(2/3) - x^2)

Options (1)

In[7]:= Together[1/(x - Sqrt[2]) + 1/(x + Sqrt[2]), Extension -> Sqrt[2]]
Out[7]= (2 x)/(-2 + x^2)

Applications (9)

Distinct denominators are multiplied

In[8]:= Together[1/x + 1/y]
Out[8]= (x + y)/(x y)

A common factor hidden across the denominators is cancelled

In[9]:= Together[1/(x - 1) - 2/(x^2 - 1)]
Out[9]= 1/(1 + x)

A telescoping sum collapses to 1

In[10]:= Together[a/(a - b) + b/(b - a)]
Out[10]= 1

The exponential kernel is a generator of the rational function field

In[11]:= Together[E^x/(E^x + 1) + 1/(E^x + 1)]
Out[11]= 1

Combination over Q(Sqrt[2])

In[12]:= Together[1/(x - Sqrt[2]) + Sqrt[2]/(x^2 - 2), Extension -> Sqrt[2]]
Out[12]= (2 Sqrt[2] + x)/(-2 + x^2)

Logarithms stay opaque: Log[x^2] is not rewritten to 2 Log[x]

In[13]:= Together[Log[x^2] + 1/x]
Out[13]= (1 + x Log[x^2])/x

An unevaluated integral is an atom, never re-evaluated with a symbol inside

In[14]:= Together[E^Cos[x] Integrate[E^-Cos[x], x]]
Out[14]= E^Cos[x] Integrate[E^(-Cos[x]), x]

Threads over lists and equations

In[15]:= Together[{1/x + 1, x == 1/y + 1}]
Out[15]= {(1 + x)/x, x == (1 + y)/y}

Inexact input is rationalised, combined and numericalised again

In[16]:= Together[0.5/x + 1/(2 x)]
Out[16]= 1/x

Options & behaviour

  • Cube-and-higher-root towers (2026-07-04): a Plus of fractions over radicals Power[base, p/q] of any index q ≥ 2 whose radicand carries a free symbol (e.g. k^(1/3)) is combined over a common denominator via FLINT (flint_algebraic_field_together), with the radicals treated as free kernels — WL-faithful: radicals stay in the denominator, no rationalisation. This generalises the sqrt-only combiner to any index. The same path serves Cancel single-fraction relation-dependent cancellations ((x^3-k)/(x-k^(1/3))) still go through the relation-aware GCD path.

Implementation notes

Algorithm. builtin_together is a FactorMemo-keyed memoisation wrapper around builtin_together_compute, so repeated Together[arg, opts] calls issued during one Simplify (which pushes a FactorMemo) hit the cache; standalone calls see no overhead. The compute routine puts everything over a common denominator and cancels.

Dispatch, FLINT build. builtin_together_compute first tries rat_canon_normalize(arg, RCM_TOGETHER) (src/poly/ratcanon.c) on exact, option-free input; MATHILDA_RATCANON=off turns this off. rat_canon_build replaces every kernel by a fresh indeterminate, giving one ordered generator tower. Transcendental kernels (Log, E^f, inverse trig) become free generators, and rt_expand_exp_sums first splits E^(a+b) so that commensurate exponentials share one fundamental. Algebraic generators (I, radicals, roots of unity) carry their minimal polynomial as a relation. rat_canon_reduce reduces num/den modulo those relations with flint_tower_reduce, maps back, and sign-normalises the result. It declines to the classical paths whenever a number-field common factor might be missed. Next come flint_cancel_fraction for algebraic extensions (including parametric Q(a, b)(Sqrt[k])) and then the plain-Q fmpz_mpoly_q fast path, both before the classical walker below. Since v0.434 two rules keep these paths value-preserving. Binding operators are opaque: poly_is_binding_operator marks unevaluated Integrate, D, Sum, Limit, Function, Hold*, Inactive[op][…] and similar heads as atoms, so the kernel substitution never descends into them and re-evaluates them with a symbol in place of the kernel. Logs are never expanded: Log[x^2] stays one generator rather than becoming 2 Log[x], which is false for x < 0.

The classical walker together_recursive recurses structurally. For a Plus[t_1, ..., t_n] it first togethers each summand, splits each into numerator/denominator via extract_num_den, computes the iterated PolynomialLCM of the denominators, then for each term forms lcm_den / den_i using cancel_exact_div_strict (exact polynomial division in Q[vars]) — a strict combine: if any quotient is not exact (a sign that PolynomialLCM was only valid in some algebraic-extension ring, e.g. multi-radical sums), it bails cleanly and leaves the Plus uncombined rather than risk the Power[Plus[...], -1]-inside-numerator GCD blowup. When all quotients are exact, it sums the rescaled numerators, multiplies by Power[lcm_den, -1], and runs cancel_recursive (PolynomialGCD-based cancellation) on the result. List/relational/logical heads thread through their args; other heads recurse and then cancel.

Crucially, together_recursive never expands Power[Plus[...], n] — extract_num_den only splits products, powers (pushing negative integer/rational exponents into the denominator), exponentials, complexes, and literal rationals; expansion is left to downstream poly-GCD with size gates. builtin_together_compute additionally handles Extension -> α (and Extension -> Automatic, which calls extension_autodetect): single-generator extensions route through together_recursive_ext over Q(α)[x]; multi-generator towers route through qa_cancel_with_tower, with nested-radical α prefiltered out and a "best generator" guided fallback (pick_best_tower_generator) gated on leaf count. A poly_find_radical_gen pass substitutes a radical generator to a fresh symbol, runs the no-extension path, and substitutes back. Inexact inputs are rationalised then re-numericalised (internal_rationalize_then_numericalize).

Data structures. Expr* trees; numerator/denominator pairs are plain Expr* out-parameters. Extension towers are QATower; exact division and LCM run on the multivariate-polynomial representation behind exact_poly_div / PolynomialLCM / PolynomialGCD. Numerator carries ATTR_LISTABLE.

Complexity / limits. Bounded by the polynomial GCD/LCM machinery on the combined fraction. The strict-quotient gate and the leaf-count gates are deliberate safeguards against multivariate-Euclid runaway on multi-radical / algebraic-extension inputs.

  • Protected, Listable.
  • Makes a sum of terms into a single rational function.
  • Value-preserving on every kernel (2026-10-17). Transcendental kernels are replaced by fresh generators only OUTSIDE variable-binding operators: an unevaluated Integrate/D/Sum/Product/Limit/Series, a Function, an Inactive[op][...] form or a Hold wrapper is an opaque atom (previously Together[E^Cos[x] Integrate[E^-Cos[x], x]] returned x, the generator having been substituted into the integrand and re-integrated). Log[...] arguments are never rewritten: Together[Log[x^2] + 1/x] is (1 + x Log[x^2])/x, not 2 Log[x] (false for x < 0), and Log[-w] is not split into I Pi + Log[w] — matching Mathematica. The same holds for Cancel and Factor.
  • Computes lowest common multiples (LCM) of denominators securely without unconditionally destroying pre-factored bases unnecessarily.
  • Handles a single symbolic base appearing with rational fractional exponents (e.g. y^(1/3), y^(2/3), y^(73/24)) by treating it as an algebraic generator: substitutes y -> g^m where m is the LCM of denominators, runs the polynomial pipeline in g, then substitutes back.
  • Option Extension -> alpha (Phase 0 of the Integrate plan) combines into a single fraction with the standard combiner, then runs Cancel[..., Extension -> alpha] on the result so algebraic-coefficient cancellations fire. Effective on simple inputs like 1/(x - Sqrt[2]) + 1/(x + Sqrt[2]), which collapses to (2 x)/(x^2 - 2). Inputs whose summands themselves carry algebraic-coefficient denominators are deferred to Phase 0.5 (which will plumb Extension through PolynomialLCM / PolynomialQuotient / together_recursive).
  • Option Extension -> Automatic with polynomial radicands (Phase E, 2026-05-25): when the input contains exactly one distinct radical Sqrt[poly] or Power[poly, 1/q] whose radicand is a polynomial in free symbols (e.g. Sqrt[p+q], Power[1+x^2, 1/3]), qa_cancel_with_poly_radical substitutes the radical with a fresh symbol S, runs Together, reduces the numerator and denominator modulo S^q - poly via PolynomialRemainder, optionally rationalises via PolynomialExtendedGCD (when it shrinks the result), and substitutes back. Sample collapses: Together[1/(x - Sqrt[p+q]) + 1/(x + Sqrt[p+q]), Extension -> Automatic] returns (2 x)/(-p - q + x^2); Cancel[(x^2 - (p+q))/(x - Sqrt[p+q]), Extension -> Automatic] returns Sqrt[p+q] + x. Multi-radical inputs (Cardano-style conjugate pairs) are rejected; the deeper limitation is documented in docs/spec/changelog/2026-05-25.md.
  • Native AlgebraicNumber-coefficient path. Same K(x) reduction as Cancel above, applied after combining the sum of fractions over a common denominator: a sum whose coefficients are AlgebraicNumber[θ, {..}] over one number field is combined and reduced natively over the antic number-field ring, value-equal to the generic path and fully reduced; declines on the multivariate case.

Attributes: Listable, Protected.

References

See also: Integrate, D, Sum, Product, Limit, Series, Function, Hold

Notes & additional examples

Notes

  • Together[expr] puts a sum of terms over a single common denominator and cancels the GCD of the result. It is the inverse of Apart. Unlike a full expansion, it does not multiply out Power[Plus, n] factors that it does not need to.
  • Kernels. Transcendental subexpressions (Log[...], E^f, inverse trig) and algebraic constants (I, radicals) are treated as generators of the rational function field. Exponentials with commensurate exponents share one generator. Logarithms are left as they are, because rewriting Log[x^2] as 2 Log[x] is false for x < 0.
  • Binding operators are atoms. Unevaluated Integrate, D, Sum, Limit, Function, Hold* and Inactive[op][...] are never looked inside.
  • Extension. Extension -> α, a list, or Automatic combines over the number field. Plain algebraic constants are often handled without it.
  • Listable, Protected. Symbolic only.
  • See also: Cancel, Apart, Factor, Numerator, Denominator, Simplify.