Skip to content

2.7.0

Latest

Choose a tag to compare

@Rafael-SOWNet Rafael-SOWNet released this 14 Nov 02:22
· 4 commits to master since this release
ad523f6

This release is about limits and compilation. On limitcheck's 40 seeds that both versions
complete, 2.6.0 answers 2,685 limits with a value other than the one the expression settles at, and
2.7.0 answers 70.
limitcheck generates limits and compares each answer with the values approaching it.
A finding is a witness, and values that settle are not a proof.

limitcheck, DEPTH=3, COUNT=600, 40 seeds 2.6.0 2.7.0
limits compared with the values they are limits of 208,475 214,183
the limit is another value than the values settle at 2,685 70
the limit is NaN where the values settle 1,519 457
the limit did not finish in 5 s 495 3

The seeds are the 42 that the PR checks use. 2.6.0, measured as its NuGet package, did not complete
two of them. On seed 19 the run ended itself, because three evaluations did not stop when cancelled, the
last in tan(tanh(x)^(x^(-1))) at 0. On seed 28 the process died with an empty log. 2.7.0, measured on
master 842e8e951, completed all 42. Of the 527 findings left on the 40 seeds, 478 are two-sided limits, and 457 of those are of an
expression with a power, a logarithm or a root, where a two-sided limit through the complex branch is what
#1019 holds for v3.

78 of the release's 281 pull requests change how a limit is taken. The descent now reads a side, a sign
and an order of vanishing where it used to substitute. It leaves a limit unevaluated where it cannot
compare the sides, which 2.6.0 answered with NaN or a wrong number. And l'Hôpital's rule is kept from
what it cannot decide. 36 PRs make the two compilers agree with evaluation. Statements, piecewise, the
combinatorial and number-theoretic functions, and matrix arguments now compile, and compiled powers,
branch cuts and values at an infinity match evaluation's. The rest of the release adds functions by name,
makes the equation solver complete on systems and radicals, and stops numerical evaluation rounding real
values onto zero or onto a nearby rational. No tier of the
Math OS roadmap is completed by this
release (see the note on #746).

Every changed answer is in BREAKING-CHANGES.md
under 2.7.0 — since 2.6.0
, with the old value, the new one and why. Read it first if your code
depends on an answer. It holds 193 entries, and 135 of them open as silent changes, where the
call still succeeds and returns something else. 62 of the entries are limits. The section opens with
the ones to read before any other: names that read differently. Each was read as something else on
2.6.0, so code that used the name for something of its own changes meaning without an error.

  • re(…), im(…), real(…) and imag(…) are the real and the imaginary part. re(z) was the variable
    re times z.
  • conjugate(…), conj(…) and arg(…) are the conjugate and the principal argument.
  • det(…), transpose(…), dot(…), cross(…), resultant(…) and trace(…) are computed, or are nodes
    of a name for a matrix. A[k, l] is an entry, counted from 1.
  • The names of functions still to come, such as zeta(…), now throw
    UnrecognizedFunctionParseException.
  • Silent: eulergamma and EulerGamma are Euler's constant, where they were a variable.

The other new functions, from polygamma to lambertw, were also products before; they are in the
table under New functions. Each name without a bracket is still a variable. Two other silent changes
are worth reading early. A computed value is no longer rounded onto zero or onto a nearby rational:
e^(-155) was 0 at a hundred digits, and 1/3 + 1e-30 was 1/3 (#2066, #2072, #2076). And |v| of a
vector is its norm over the complex numbers: abs([3 i, 4]) was sqrt(7), and is 5 (#2431).

AssemblyVersion stays 2.0.0.0. The recorded public surface has 485 additions and no
removals
, so code that compiled against 2.6.0 still compiles, and code bound against it still
binds.

Wrong answers fixed

Each item has an entry in BREAKING-CHANGES.md with both values.

  • Limits that had a value, and the wrong one.
    • log(x, 0) at 0 from the right was 0, where it is +oo. An infinity that does not depend on the
      variable was read as a coefficient (#2374).
    • x * floor(1/x^2) at 0 from the right was 0, where it is +oo, and floor(x)/x at +oo was 0,
      where it is 1 (#2430). x^2 * floor(1/x^2) two-sided was 0, where it is 1 (#2419, #2430).
    • l'Hôpital's rule was applied across the jumps of a step function
      (#2281, #2284). It was applied to
      a quotient of two limits it had not taken, read as infinite because each held +oo as its
      destination (#2360).
      And it gave a quotient of logarithms over a vanishing divisor the wrong sign: ln(x)/ln(cos(x)) at
      0+ was -oo, where it is +oo (#2267, #2275).
    • arccot(x) at 0 was pi/2 from both sides. It jumps there, so the left limit is -pi/2 and the
      two-sided one does not exist (#2420).
    • 1 / log(x^2, cos(x)) at 0 was -oo, where it is +oo from each side. It is left unevaluated now
      (#2426). floor(x)^x at 0
      from the right was 1, where it is 0 (#2332). tanh(log(arcsin(x), x)) at 0 from the right was
      1, where it is tanh(1) (#2369). (log(x, 1/2))^(exp(x) - sgn(x)) at 0 from the right was 0,
      where it is 1 (#2357). (abs(x) - x) / (abs(x) - x) at 1 was 1, where it has no value near the
      point (#2379).
    • exp(x) / exp(cos(x)) at -oo was NaN, the claim that the limit does not exist, where it is 0.
      So were x * exp(sin(1/x)) at 0, which is 0, and 1 / (x^2 (3 + cos(1/x))) at 0, which is +oo.
      A part bounded away from 0 now settles the limit it has none of its own in (#2439).
  • Equations answered with missing roots, or with points that are not roots.
    • A polynomial system lost solutions: x y = 0, x + y^2 = 1 answered only [1, 0]
      (#2126, #2127). A square system was answered
      with rows that are no solution (#2123, #2125),
      and a system with a copy of one of its rows (#2138, #2158).
      A system with a product equation lost a branch (#2128, #2129).
    • N/D = 0 lost roots: (18x^2 - 3x^3 - 4x^4 + x^5)/(9x^2 - 6x^4 + x^6) = 0 answered { 3 }, where it is
      { -2, 3 }, and a non-strict inequality lost them with it (#2320). An inequality was answered at a
      point where its expression has no value: (4x - x^3)/x > 0 included 0 (#2321).
    • A polynomial with no roots in closed form was answered with one root of five (#2324, #2326). An
      equation in a radical and powers of x could miss roots or include a point that is not one (#2323,
      #2325). A negative whole power was inverted to no roots
      (#2144, #2154).
    • MathS.SolveEquation("x + 1 = 3", "x") was { x : x + 1 = 3 and 3 = 0 }. An equality is now read as
      a difference equal to zero (#1673, #2061).
    • (-2)^x + 4^x = 0 overflowed the stack and took the process down. It is solved now, and Newton's
      method no longer keeps a point that is only crawling towards t = 0
      (#2424, #2432).
    • Over the reals, e^x + 1 = 0 was answered { ln(-1) }, and ln(-1) is i pi. 2^x = -3 was
      { log(2, -3) }, and e^x - 2e^(-x) - 1 = 0 was { ln(-1), ln(2) }
      (#2425, #2433).
  • Rewrite rules that held only where they were written to
    (#2428, #2434).
    • Simplify gathered x^n / y^(2n) into (x / y^2)^n. At x = 1, y = -1, n = 1/2 the first is -1 and the
      second 1. It now carries the guard a^n / b^n has: n whole, or both bases positive reals.
    • Simplify answered (a > b and b > c) implies a > c with True over the complex numbers, where at
      a = i, b = 1, c = 0 it has no truth value. It is still True over the reals.
    • Through the rule registry, arcsin(0/x) was rewritten to arccsc(x/0), and sgn(x) (y x) / |x| to
      y for an x not known to be real. Simplify's answers were not affected by these two.
  • Matrices and vectors.
    • [[1, 2], [3, 4]] / [[1, 2], [3, 4]] was [[1, 1], [1, 1]], divided entry by entry. A matrix is
      now divided, raised to a power and compared as a matrix
      (#2141, #2155).
    • [[a, b], [2a, 2b]].Rank was 2. A symbolic pivot is now decided before it is chosen
      (#2345, #2350).
    • A lambda applied to a vector multiplied by it entry by entry
      (#2132, #2156).
    • abs([1 + i, 1 - i]) was 0, where it is 2
      (#2423, #2431).
    • det(A) with [[1, 2], [3, 4]] put in for A evaluated to [[det, det * 2], [det * 3, det * 4]].
      It is -2 (#2427,
      #2147, #2436).
  • Compiled functions that disagreed with evaluation.
    • ln(cos(x)) at 2 compiled to the conjugate of its value, because System.Numerics.Complex reads a
      real number's -0 imaginary part as the lower side of the cut
      (#2236,
      #2239, #2240).
    • A compiled power over Complex had no value at an infinity, and gave 0 for 0^(-1) and 1 for
      0^0 (#2225, #2231). x^(1/3) at
      -8 was not real (#2318).
    • A scalar over a matrix argument compiled as the scalar over each entry. [[1, 0]] * A * [[0], [1]]
      with A a matrix argument compiled to 0, because simplification read A as a number. A
      non-square matrix was squared entry by entry
      (#2422, #2429).
    • not (x > 1) at NaN compiled to True (#2208). (x provided x > 1)^0 at 0.7 compiled to 1
      (#2250, #2252).
  • Numerical evaluation.
    • sqrt(2/10^20) was 0. The exact-root search rounded each candidate to six digits
      (#2065, #2067).
    • e^(-155) was 0 at a hundred digits, and sin(10^(-60)) was 0
      (#2074, #2072, #2076). 1/3 + 1e-30 was
      1/3 (#2066).
    • DefiniteIntegral of x^2 over [0, 1] was off in the third digit and printed to a hundred. It is
      Gauss–Legendre now, and gives only the digits it knows
      (#1675, #2063). Two equal expressions
      computed by different routes compared unequal numerically
      (#1674, #2062).
    • 0.9999999999999999999999999999m was the Rational 1/1, which is not equal to 1
      (#2069, #2071). 6 mod (1/27) was 1/27
      (#2327). round(10^120 + 2/3) was 10^120
      (#2282, #2285). binomial(450.5, 3.25)
      was +oo (#2338). FromBaseN("80000000", 16) was -2147483648
      (#2343,
      #2344, #2351).
    • An exact power too large to build did not return: 2^(10^9), 2^(10^9) - 2^(10^9) and
      2^(10^9) > 2^(10^9 - 1) hung on 2.6.0. Past sixteen million bits such a power is now left written,
      never +oo or 0. Differences, quotients and comparisons are settled where structure, the exponents
      or the logarithms of the magnitudes settle them: those three are 2 ^ 1000000000, 0 and True
      (part of #1448, #2347, #2437).
  • Values where there are none. sgn(NaN) was 1
    (#2241, #2243), and log(0, 2) was 0
    (#2255, #2258).
  • Sets. [0; 10] \ (2; 3) was [0; 3]
    (#2290, #2300). Membership in a union was
    False where one side left it open: (10^30 + 57) in (PP \/ [0; 1])
    (#2219, #2221).
  • Printing. sinh(-5/4) printed --5/4, which reads back as -(-5)/4, a different expression
    (#2264, #2265). am_series of sin(x) at
    degree 7 dropped the seventh-degree term (#2299, #2303).

Limits

The descent is the limit code that takes an expression apart and asks each part for its own limit.
In this release it:

  • Reads a side. A step function at a jump takes the side its argument arrives from. That side is
    read off the slope, off the parts of a quotient, and through a change of variable. A one-sided
    limit asks the parts of a sum or product from its side.
  • Reads a sign and an order. It reads a power's sign from its base, a vanishing base on the side
    approached, and a real power of a vanishing function by its order.
  • Leaves a limit unevaluated where it cannot compare the sides. 2.6.0 answered NaN there, which
    says the limit does not exist. A side that stops at 0 * floor(-oo) or at c / 0 was never
    compared, which is not the same as a side without a limit.
  • Keeps l'Hôpital's rule to what it can decide. It cancels a factor written on both sides,
    leaves out what only makes the derivatives larger, takes out a factor continuous at the point, and
    is not applied across a jump or to a limit nobody took.
  • Gives limits to more functions. erf, erfc, erfi, Si, Ci, Shi, Chi, Ei and li have
    their limits (#2373), as does a modulus (#2371, #2372). A limit of derivative(f, x) takes the
    derivative first (#2390).
  • Remembers what it has found within one question. tanh(log(arcsin(x), x)) at 0 from the left
    took 9.4 s on master before #2408 and takes 0.4 s.
  • Reads a bound. A part that stays between two positive bounds, such as e^(cos(x)), settles a
    quotient, a product or a sum it has no limit of its own in. x + sin(x) at +oo is +oo. Where the
    bound reaches 0 nothing is claimed: x / (1 + cos(x)) at +oo stays unevaluated (#2439).

PRs: #2268, #2275, #2276, #2278, #2283, #2284, #2294, #2295, #2332, #2334, #2336, #2354–#2362, #2364–#2366,
#2368–#2395, #2397–#2420, #2426, #2430, #2439.

Compilation

FastExpression and the LINQ compiler now give what evaluation gives, and refuse what they cannot
compile with UncompilableNodeException rather than a wrong value.

  • New in the compilers: statements, provided and piecewise (#2208, #2209, #2228, #2229, #2246),
    membership, divisibility, congruences, quantifiers, subsets and cardinalities over finite sets
    (#2223, #2233, #2234), mod over Complex (#2210), the combinatorial, polygamma, Lambert W, Catalan
    and number-theoretic functions (#2213–#2218, #2340), and the conjugate, the argument, the parts and
    the Iverson bracket (#2196, #2312).
  • Matrices: a matrix argument is taken and given as double[,], Complex[,], float[,],
    int[,], long[,] or BigInteger[,], with its inverse and whole powers
    (#2422, #2289, #2429). A function of a matrix
    argument is the function of each entry, as in evaluation, and a one-dimensional array is a column
    vector (#2435). exp(A) is not the matrix exponential, which evaluation does not compute either.
    det, transpose, trace and an entry A[k, l] of a matrix argument compile. The determinant is
    taken by Bareiss elimination, exact over long (#2436).
  • Only the case taken is computed. Both compilers now jump over the cases a piecewise or a
    provided does not take, where they computed every case and kept one. In a single run,
    piecewise(primepi(x) provided x < 100, 0) at 9999991 went from 17,769 µs to 0.26 µs in FastExpression
    and from 18,173 µs to 0.03 µs in LINQ over Complex
    (#2195, #2438).
  • Agreement with evaluation: powers, products and arithmetic at an infinity and at zero (#2226,
    #2231, #2249, #2252), branch cuts (#2240), division and remainders by zero (#2288, #2328, #2333),
    max and min off the real line (#2311), odd roots of negative reals (#2318), and constants and
    sgn(0) in LINQ (#2242).
  • MathS.Settings.RefuseNonRealCompilation, off by default, refuses to compile over double
    what is not real (#2286, #2297).

PRs: #2196, #2208–#2210, #2213–#2218, #2223, #2226, #2228, #2229, #2231, #2233, #2234, #2240, #2242,
#2246, #2249, #2251, #2252, #2288, #2289, #2297, #2311, #2312, #2318, #2328, #2333, #2339, #2340,
#2429, #2435, #2438.

Equations and systems

  • Systems with more or fewer equations than unknowns are solved by elimination, or declined with
    null where WrongNumberOfArgumentsException was thrown (#2124). A polynomial system keeps all of
    its solutions, a square system answers only rows that solve it, and a product equation is solved
    branch by branch (#2125, #2127, #2129, #2158, #2322).
  • Polynomials: a quartic that is biquadratic once depressed, a shifted cube, and a polynomial with
    real coefficients by Durand–Kerner, so every root is answered (#2314, #2315, #2317, #2324, #2326).
    A quadratic whose discriminant is a square has no root sign in its answer (#2170, #2173).
  • Radicals: a radical times a power of its variable is one fractional power, two different square
    roots are squared away twice, and a root of a raised equation with a parameter is provided it is one
    (#2323, #2325, #2331, #2335, #2337). A fractional power is inverted where its values lie (#2183).
  • Other forms: a linear function times an exponential by Lambert W (#2203), an equation linear in
    logarithms (#2316), and a modulus of a polynomial split at its real roots (#2178, #2307, #2309).
  • Over the reals, an exponential equation has no root where the power would have to be
    non-positive. That is decided on an enclosure of the value, so a value that cannot be told from the
    positive reals keeps its root (#2433).

PRs: #2061, #2124, #2125, #2127, #2129, #2154, #2158, #2163, #2170, #2173, #2178, #2183, #2203, #2307,
#2309, #2310, #2313–#2317, #2320–#2326, #2331, #2335, #2337, #2432, #2433.

Matrices and vectors

Matrix.Eigenvalues (#1676, #2064). The
inverse is the adjugate over the determinant, with no pivot condition (#2353). Rank and the row
echelon forms decide a symbolic pivot first, divide exactly, and exist for a 1x1 matrix (#2272, #2279,
#2350). det, transpose, dot, cross and resultant are functions in an expression (#2180).
det, transpose and trace of a name, and an entry A[k, l] counted from 1, are nodes, carried out
once the name is a matrix. A product with a transpose in it is no longer reordered, since matrices do
not commute (#2436). MathS.Matrices has Determinant, Transpose, Trace and Entry. Also,
laplacian, jacobian and hessian are computed into derivatives (#2190). Matrix division, powers
and comparison (#2155) and the vector norm (#2431) are in the list above.

New functions

Name PR
polygamma(n, z), digamma(z) the polygamma functions; x! differentiates through them #2068
gamma(a, z) the upper incomplete gamma function #2077
Re, Im (re, im, real, imag) the real and the imaginary part #2185
conjugate, conj, arg the complex conjugate and the principal argument #2181
n!! the double factorial #2187
mobius, divisorsigma, primenu, primeomega, primepi number-theoretic functions #2188
fallingfactorial, risingfactorial factorial powers #2194
multinomial the multinomial coefficient #2197
catalannumber the Catalan numbers #2198, #2349
harmonicnumber(n), harmonicnumber(n, m) the harmonic numbers #2200
forwarddifference(f, k) f(k + 1) - f(k) #2201
lambertw(z), lambertw(k, z), productlog the Lambert W function #2202, #2263
eulergamma Euler's constant #2204

Also: x_1_2 is a name (#2070); a binomial with a whole upper argument and a fractional lower one is
evaluated, and is 0 at a pole of its denominator (#2211, #2212); the factorial and the gamma function
are defined off the real line (#2260). The names of functions still to come are refused by name
(#2157, #2184).

Integration

The upper incomplete gamma function is a node, evaluated to any precision anywhere in the complex
plane (#2075, #2077). The integrator reaches
it as an answer for a power beside an exponential of a power, beside a sine or a cosine, and beside a
Laurent polynomial in an exponential. It also integrates the function itself by parts. x^100 e^(-a x)
is -a^(-101) gamma(101, a x). Polygamma functions integrate to the order below (#2073). A
definite integral of a floor or a ceiling is the sum over its pieces (#2102), and one whose bound has
no decided limit is left as written (#2081, #2101).

PRs: #2063, #2073, #2078–#2080, #2082–#2088, #2090–#2103, #2105, #2106.

Numbers and evaluation

  • A computed value becomes a rational only within half the working digits, and zero only where its
    terms cancelled (#2066, #2071, #2072, #2076). Numerical equality is to half the evaluation's digits
    (#2062).
  • An exact power too large to build is left written, and EvalNumerical refuses it with
    CannotEvalException (#2347, #2437). A complex product past the exponent range
    has its parts (#2348). Large factorials are a balanced product, and a quotient of them is divided
    before it is rounded (#2329, #2330, #2338). A whole power is built by a loop over the exponent's bits
    (#2363).
  • Number theory past long. Primality is decided by Miller–Rabin and Lucas–Lehmer
    (#2230, #2232). Factorisation, the
    divisor count, the totient and IsPrime answer past 2^63: Factorize(2^64) threw OverflowException,
    and the largest prime below 2^63 did not finish
    (#2341,
    #2342, #2352). Base conversion reaches
    base 36 and refuses a digit not in the base (#2351). round is exact (#2285). An exact rational is
    zero, positive or negative as it is (#2280).

PRs: #2062, #2066, #2067, #2071, #2072, #2076, #2232, #2280, #2285, #2327, #2329, #2330, #2338, #2347–#2349,
#2351, #2352, #2363, #2437.

Simplification and statements

A cosine of a sum is expanded as a sine of one is (#2161). The Pythagorean identities are found
anywhere in a sum, and a trigonometric identity is decided over the sines and cosines of its base
angles (#2175–#2177, #2179). A sum of fractions that is a constant simplifies to it (#2174). A factor
held to a power cancels (#2306). Simplify adds no condition the input does not have (#2171, #2186,
#2193). A sine or cosine with no real radical form stays as written: sin(pi/7) was a page of complex
radicals (#2308). A long chain of sums is simplified without a recursion as deep as the chain (#2167).
A Taylor expansion simplifies each derivative before taking the next: sin(x)/x to order 7 at 1 was
36,421 characters (#2302). Under a quantifier, a whole number of periods comes out of a trigonometric
function, and a principal root is read with what the quantifiers establish (#2205, #2206). Membership
in a set operation is decided by Kleene's connectives (#2221). Four rewrite rules hold only where
they are written to (#2434, in the list above).

PRs: #2156, #2161, #2167, #2171, #2174–#2177, #2179, #2186, #2192, #2193, #2199, #2205, #2206, #2221,
#2243, #2245, #2257, #2258, #2261, #2262, #2265, #2300, #2302–#2306, #2308, #2434.

Speed

Measured as a pair: v2.6.0 beside 842e8e95, the last kernel change before the release. Both were measured
twice each, interleaved, in one run on one CI runner
(version_performance_control.md,
#2441).

Allocation, which is deterministic (a commit's two measurements agree to 0.03%):

  • SolveHard is down 4.7% and SolveMediumHard 3.5%.
  • SimplifyHard is up 2.4%, in three steps each inside the 3% gate, and Derivate is up 1.9%.
  • Compiling allocates more: CompileEasy +33% and CompileHard +42%, from the nodes the compilers learned.

Timing, read only where both pairs agree and lie outside the run's own spread of up to 9.8%:

  • CompileEasy is up 24%, with its allocation.
  • CompileHard is down 12%, RunHard 12% and RunMedium 4%.

Single runs reported in the entries: a one-sided x * log(2 + x, x) at 0 took 27 s and takes 0.25 s
(#2384); tan(x) * x^(x - 1) at 0 took 11 s and takes 0.21 s (#2417); phi(2^62) took 2.1 s and takes
0.11 s cold (#2352).

Tools

  • The MCP server answers from a catalogue of the library's operations, 33 of them, by name
    (#2121, #2122). am_classify is served only by amcli mcp --preliminary (#2113).
  • amcli installs from Nix and the AUR (#2207).
  • The Binder image is built from this repository, and the Lab's notebooks and articles are moved here
    (#2104, #2107, #2110). The notebook extension registers its LaTeX formatters by reflection, drops
    polyfill.io, and pins a patched System.Text.Json (#2111, #2112, #2116).

Checked in CI

The Windows test leg runs the whole suite in Release and fails when it does not. The Linux and macOS
legs run it without instrumenting it (#2165, #2168). Coverage reaches Codecov, with every upload
signed in through OIDC (#2162, #2172). CI installs the GA .NET 10 SDK (#2367).

Known issues

  • +oo and -oo are members of RR and CC. Decided for v3
    (#2220).
  • A quotient by a reciprocal, 1/(1/x) or x * (1 - 1/x), simplifies to an answer with a value at
    x = 0, where the input has none. Decided for v3
    (#1648,
    #2134 row 1).
  • 3 i parses as 3^i (#1503), and a != b
    as a! = b (#1225).
  • 2 + 2^(-100) = 2 is True, because numbers are compared within a tolerance
    (#1376,
    #1019 §10).
  • With downcasting off, EvalNumerical loses values near the ends of the exponent range
    (#1498).
  • (3+4i)^2000 evaluates to +oo + +ooi. It was NaN on 2.6.0.
  • Under the real codomain, the roots of polynomial and trigonometric equations are not filtered:
    x^2 = -1 gives { i, -i }.

Pull requests in this release

281 PRs, listed by number below. They are the 281 commits of v2.6.0..ad523f67e. Every one is a PR.

Workspace, process and CI, with no change to the shipped libraries: #2107, #2110, #2117, #2119, #2159, #2165, #2169, #2172, #2191, #2367, #2421.

2061 2062 2063 2064 2066 2067 2068 2070 2071 2072 2073 2076 2077 2078 2079 2080 2082 2083 2084 2085
2086 2087 2088 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
2107 2110 2111 2112 2113 2115 2116 2117 2119 2121 2122 2124 2125 2127 2129 2130 2154 2155 2156 2157
2158 2159 2161 2162 2163 2165 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180
2181 2183 2184 2185 2186 2187 2188 2190 2191 2192 2193 2194 2196 2197 2198 2199 2200 2201 2202 2203
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2221 2223 2226 2228 2229
2231 2232 2233 2234 2240 2242 2243 2245 2246 2249 2251 2252 2257 2258 2260 2261 2262 2263 2265 2268
2272 2275 2276 2278 2279 2280 2283 2284 2285 2288 2289 2294 2295 2297 2300 2302 2303 2304 2305 2306
2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2320 2321 2322 2323 2324 2325 2326 2327
2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2347 2348 2349 2350 2351 2352 2353
2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373
2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
2394 2395 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414
2415 2416 2417 2418 2419 2420 2421 2426 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441