| | | 1 | | //======================================================================= |
| | | 2 | | // FiniteAxisValueRoots.cs |
| | | 3 | | //======================================================================= |
| | | 4 | | // MIT License, Copyright (c) 2024-present David Oravsky (mrdav30) |
| | | 5 | | // See LICENSE file in the project root for full license information. |
| | | 6 | | //======================================================================= |
| | | 7 | | |
| | | 8 | | using System; |
| | | 9 | | |
| | | 10 | | namespace FixedMathSharp.Geometry; |
| | | 11 | | |
| | | 12 | | /// <summary> |
| | | 13 | | /// Authoritative distinct-root count and optional compact cells for one fixed |
| | | 14 | | /// polynomial on (0,1]. A failed compact batch still owns the complete count; |
| | | 15 | | /// its partial cells are never consumed. Storage is borrowed and not mutated. |
| | | 16 | | /// </summary> |
| | | 17 | | internal readonly ref struct FiniteAxisValueRoots |
| | | 18 | | { |
| | | 19 | | private readonly ReadOnlySpan<ulong> _cells; |
| | | 20 | | private readonly ReadOnlySpan<int> _shifts; |
| | | 21 | | private readonly int _rationalMask; |
| | | 22 | | internal int Count { get; } |
| | | 23 | | internal bool HasCompactCells { get; } |
| | | 24 | | internal bool HasRepeatedRoots { get; } |
| | | 25 | | |
| | | 26 | | internal FiniteAxisValueRoots(ReadOnlySpan<ulong> cells, ReadOnlySpan<int> shifts, |
| | | 27 | | int count, int rationalMask, bool compact, bool repeated) |
| | | 28 | | { |
| | 29257 | 29 | | _cells = cells; |
| | 29257 | 30 | | _shifts = shifts; |
| | 29257 | 31 | | _rationalMask = rationalMask; |
| | 29257 | 32 | | Count = count; |
| | 29257 | 33 | | HasCompactCells = compact; |
| | 29257 | 34 | | HasRepeatedRoots = repeated; |
| | 29257 | 35 | | } |
| | | 36 | | |
| | | 37 | | /// <summary> |
| | | 38 | | /// Materializes ordinal in [0,Count) for the unchanged polynomial used to |
| | | 39 | | /// create this view. The result borrows only the explicit polynomial and |
| | | 40 | | /// destination spans, not the compact cache. Fallback requires the full |
| | | 41 | | /// GetFiniteValueRootCellWords capacity; compact copying needs its active |
| | | 42 | | /// numerator words plus capacity for the nonrational upper endpoint. |
| | | 43 | | /// </summary> |
| | | 44 | | internal static FiniteAxisValueRoot GetRoot(scoped FiniteAxisValueRoots roots, |
| | | 45 | | int ordinal, ReadOnlySpan<ulong> coefficients, |
| | | 46 | | ReadOnlySpan<sbyte> signs, Span<ulong> cell) |
| | | 47 | | { |
| | | 48 | | System.Diagnostics.Debug.Assert(ordinal >= 0 && ordinal < roots.Count); |
| | 24892 | 49 | | int words = coefficients.Length / signs.Length; |
| | 24892 | 50 | | int degree = signs.Length - 1; |
| | | 51 | | // A valid ordinal proves that this unchanged polynomial has a root, |
| | | 52 | | // so trimming cannot reach a constant or zero polynomial. |
| | 25927 | 53 | | while (signs[degree] == 0) |
| | 1035 | 54 | | degree--; |
| | 24892 | 55 | | coefficients = coefficients[..((degree + 1) * words)]; |
| | 24892 | 56 | | signs = signs[..(degree + 1)]; |
| | 24892 | 57 | | if (!roots.HasCompactCells) |
| | 18 | 58 | | return WideFiniteAxisIntersection.GetKnownFiniteValueRoot(coefficients, signs, ordinal, roots.Count, cell); |
| | 24874 | 59 | | int cellWords = roots._cells.Length / 8; |
| | 24874 | 60 | | ReadOnlySpan<ulong> source = roots._cells.Slice(ordinal * cellWords, cellWords); |
| | 24874 | 61 | | cell.Clear(); |
| | 24874 | 62 | | source[..WideArithmetic.GetActiveMagnitudeLength(source)].CopyTo(cell); |
| | 24874 | 63 | | return new FiniteAxisValueRoot |
| | 24874 | 64 | | { |
| | 24874 | 65 | | Coefficients = coefficients, Signs = signs, LowerNumerator = cell, |
| | 24874 | 66 | | DenominatorShift = roots._shifts[ordinal], Ordinal = ordinal, |
| | 24874 | 67 | | IsRational = (roots._rationalMask & (1 << ordinal)) != 0 |
| | 24874 | 68 | | }; |
| | | 69 | | } |
| | | 70 | | } |