Skip to content

ContinuedFraction of a quadratic irrational is its periodic form and takes exactly n terms, of another exact real the terms a doubled-precision check vouches for; FromContinuedFraction reads a period back - #571

Open
enumeratio wants to merge 1 commit into
cortex-js:mainfrom
enumeratio:continued-fraction-periodic

Conversation

@enumeratio

Copy link
Copy Markdown
Contributor

ContinuedFraction(Sqrt(2)) is [1, [2]], ContinuedFraction(ExponentialE, 40) is its 40 terms, and FromContinuedFraction([1, [2]]) is Sqrt(2). Fixes #570

Rules (numerics/continued-fractions.ts, new; library/number-theory.ts):

  • An exact quadratic irrational, read from Add, Multiply, Divide, Negate, Subtract, Sqrt, Root(·, 2) and Power(·, 1/2) of rationals and radical literals, expands by the recurrence a = ⌊(P + √D)/Q⌋, P' = aQ − P, Q' = (D − P'²)/Q, with Q | D − P² ensured at the start so the state stays integral. The first repeated state (P, Q) closes the period (Lagrange's theorem), and the first term is always in the leading part: [1, [2]], [1, [1]] for the golden ratio, [1, 7, [1, 2, 1, 8, 13, 8]] for (3 + √7)/5, as Wolfram writes them. With a count n the result is exactly n flat terms. A sum or product of different radicals is not one quadratic field and goes the way of the next rule.
  • Another exact real (ExponentialE, Pi, Exp(1/2)) is computed at 2n + 30 digits (_withTransientPrecision), the terms common to both ends of [v − ε, v + ε] are kept less the last (a terminating end writes it two ways), and the same n terms must come out of twice the digits. Not reached within 20000 digits, or the two disagree: unevaluated. n defaults to 20.
  • .N() reads the operand as written: it had already made it a float, which has no terms past its precision. The result of .N() is the result of evaluate(), floated the way the wrapper does for a float operand.
  • FromContinuedFraction reads a last element that is a list as the period [p₀, …, p_{k−1}]: the matrix of the period gives the tail y as the positive root of C y² + (D − A) y − B = 0, and the leading terms are folded back (x = a₀ + 1/(a₁ + …)). An empty period, a non-positive period term and a non-integer term decline. .N(), and a float term, give a float.
  • Caps: MAX_CONTINUED_FRACTION_TERMS (100000) on a period or a count, MAX_CERTIFIED_DIGITS on the precision. Past a cap the call is unevaluated, not truncated.

The signature is (real, integer?) -> list<integer | list<integer>>. A rational, a perfect square and an inexact operand are unchanged (flat list). A negative quadratic irrational uses the floor expansion, as a negative rational does (-√2 is [-2, 1, 1, [2]]); Wolfram's signed terms are not followed.

isqrt in numerics/diophantine.ts is exported for the recurrence. The compile targets have no lowering for ContinuedFraction, so nothing changes there.

Tests: test/compute-engine/continued-fraction-periodic.test.ts (new): ten quadratic irrationals against Wolfram under evaluate() and .N(), n terms, E to 40 and Pi to 30 terms, the cap, and FromContinuedFraction (the same four forms, .N(), declines, and the round trip for every expansion above). Pinned tests changed: wester.test.ts, ContinuedFraction(Sqrt(23)) was twenty terms ending …, 1, 4, now [4, [1, 3, 1, 8]] (and ten terms with a count); the result type of the broadcast ContinuedFraction row in broadcast-collection-valued-results.test.ts, list<list<integer>> to list<list<integer | list<integer>>>.

Overlap: #521, #522, #543, #545 and #547 edit number-theory.ts (other heads; the helpers sit before canEnumerate acceptance, and the CHANGELOG and docs entries will need a rebase); #493 and others edit the same docs tables.

Left out: a float operand's own last term is a truncation of its approximant (ContinuedFraction(2.718281828459045, 40) still ends …, 12, 2); {1, 2, {}} (an empty period) is declined where Wolfram answers 3/2.

… …, [period]] and takes exactly n terms, of another exact real the terms a doubled-precision check vouches for (ExponentialE, 40 had a wrong last term), and FromContinuedFraction reads a trailing period back as the quadratic irrational; add regression tests. Fix cortex-js#570
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

ContinuedFraction: Sqrt(2) is not periodic, E has a wrong last term, and FromContinuedFraction cannot read a period

1 participant