| | | 1 | | //======================================================================= |
| | | 2 | | // WideFiniteConeIntersection.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 | | namespace FixedMathSharp.Geometry; |
| | | 9 | | |
| | | 10 | | /// <summary> |
| | | 11 | | /// Owns exact full-domain finite-cone containment and segment reduction. |
| | | 12 | | /// </summary> |
| | | 13 | | internal static class WideFiniteConeIntersection |
| | | 14 | | { |
| | 1 | 15 | | private static readonly Signed192 One = Signed192.Signed(1L); |
| | 1 | 16 | | private static readonly Signed192 Four = Signed192.Signed(4L); |
| | 1 | 17 | | private static readonly Signed192 AxisScaleSquared = new(0UL, 1UL, 0UL); |
| | | 18 | | |
| | | 19 | | #region Nested Types |
| | | 20 | | |
| | | 21 | | private readonly struct RationalBound |
| | | 22 | | { |
| | | 23 | | internal readonly Signed192 Numerator; |
| | | 24 | | internal readonly Signed192 Denominator; |
| | | 25 | | |
| | | 26 | | internal RationalBound(Signed192 numerator, Signed192 denominator) |
| | | 27 | | { |
| | 5074 | 28 | | Numerator = numerator; |
| | 5074 | 29 | | Denominator = denominator; |
| | 5074 | 30 | | } |
| | | 31 | | } |
| | | 32 | | |
| | | 33 | | private readonly struct ConeData |
| | | 34 | | { |
| | | 35 | | internal readonly Signed192 StartAxial; |
| | | 36 | | internal readonly Signed192 AxialVelocity; |
| | | 37 | | internal readonly Signed192 MaximumAxial; |
| | | 38 | | internal readonly Signed576 Coefficient; |
| | | 39 | | internal readonly Signed576 Projection; |
| | | 40 | | internal readonly Signed576 Constant; |
| | | 41 | | |
| | | 42 | | internal ConeData( |
| | | 43 | | Signed192 startAxial, |
| | | 44 | | Signed192 axialVelocity, |
| | | 45 | | Signed192 maximumAxial, |
| | | 46 | | Signed576 coefficient, |
| | | 47 | | Signed576 projection, |
| | | 48 | | Signed576 constant) |
| | | 49 | | { |
| | 2757 | 50 | | StartAxial = startAxial; |
| | 2757 | 51 | | AxialVelocity = axialVelocity; |
| | 2757 | 52 | | MaximumAxial = maximumAxial; |
| | 2757 | 53 | | Coefficient = coefficient; |
| | 2757 | 54 | | Projection = projection; |
| | 2757 | 55 | | Constant = constant; |
| | 2757 | 56 | | } |
| | | 57 | | |
| | | 58 | | internal ConeData NegatedPolynomial() => |
| | 13 | 59 | | new( |
| | 13 | 60 | | StartAxial, |
| | 13 | 61 | | AxialVelocity, |
| | 13 | 62 | | MaximumAxial, |
| | 13 | 63 | | WideArithmetic.SubtractSigned576(default, Coefficient), |
| | 13 | 64 | | WideArithmetic.SubtractSigned576(default, Projection), |
| | 13 | 65 | | WideArithmetic.SubtractSigned576(default, Constant)); |
| | | 66 | | } |
| | | 67 | | |
| | | 68 | | #endregion |
| | | 69 | | |
| | | 70 | | internal static bool TryGetApexInterval( |
| | | 71 | | FixedSegment query, |
| | | 72 | | Vector3d apex, |
| | | 73 | | Vector3d apexToBaseDirection, |
| | | 74 | | Fixed64 height, |
| | | 75 | | Fixed64 baseRadius, |
| | | 76 | | out Fixed64 entry, |
| | | 77 | | out Fixed64 exit, |
| | | 78 | | out bool startContained, |
| | | 79 | | out bool endContainedStrict) => |
| | 43 | 80 | | TrySolve( |
| | 43 | 81 | | CreateApexData(query, apex, apexToBaseDirection, height, baseRadius), |
| | 43 | 82 | | Fixed64.One, |
| | 43 | 83 | | out entry, |
| | 43 | 84 | | out exit, |
| | 43 | 85 | | out startContained, |
| | 43 | 86 | | out endContainedStrict); |
| | | 87 | | |
| | | 88 | | internal static bool TrySolveUnitPolynomial( |
| | | 89 | | Signed576 coefficient, |
| | | 90 | | Signed576 projection, |
| | | 91 | | Signed576 constant, |
| | | 92 | | Fixed64 outputScale, |
| | | 93 | | out Fixed64 entry, |
| | | 94 | | out Fixed64 exit) => |
| | 1862 | 95 | | TrySolveBoundedPolynomial( |
| | 1862 | 96 | | new ConeData(default, default, default, coefficient, projection, constant), |
| | 1862 | 97 | | new RationalBound(default, One), |
| | 1862 | 98 | | new RationalBound(One, One), |
| | 1862 | 99 | | outputScale, |
| | 1862 | 100 | | out entry, |
| | 1862 | 101 | | out exit); |
| | | 102 | | |
| | | 103 | | internal static int GetPolynomialSignAtScaledParameter( |
| | | 104 | | Signed576 coefficient, |
| | | 105 | | Signed576 projection, |
| | | 106 | | Signed576 constant, |
| | | 107 | | Fixed64 parameter, |
| | | 108 | | Fixed64 scale) => |
| | 8 | 109 | | Evaluate( |
| | 8 | 110 | | new ConeData(default, default, default, coefficient, projection, constant), |
| | 8 | 111 | | Signed192.Signed(parameter.m_rawValue), |
| | 8 | 112 | | Signed192.Signed(scale.m_rawValue)).Sign; |
| | | 113 | | |
| | | 114 | | internal static int GetPolynomialSignAtRationalParameter( |
| | | 115 | | Signed576 coefficient, |
| | | 116 | | Signed576 projection, |
| | | 117 | | Signed576 constant, |
| | | 118 | | Signed192 numerator, |
| | | 119 | | Signed192 denominator) => |
| | 188 | 120 | | Evaluate( |
| | 188 | 121 | | new ConeData(default, default, default, coefficient, projection, constant), |
| | 188 | 122 | | numerator, |
| | 188 | 123 | | denominator).Sign; |
| | | 124 | | |
| | | 125 | | internal static bool TryGetApexDistanceInterval( |
| | | 126 | | FixedSegment query, |
| | | 127 | | Vector3d apex, |
| | | 128 | | Vector3d apexToBaseDirection, |
| | | 129 | | Fixed64 height, |
| | | 130 | | Fixed64 baseRadius, |
| | | 131 | | Fixed64 totalDistance, |
| | | 132 | | out Fixed64 entry, |
| | | 133 | | out Fixed64 exit, |
| | | 134 | | out bool startContained, |
| | | 135 | | out bool endContainedStrict) => |
| | 99 | 136 | | TrySolve( |
| | 99 | 137 | | CreateApexData(query, apex, apexToBaseDirection, height, baseRadius), |
| | 99 | 138 | | totalDistance, |
| | 99 | 139 | | out entry, |
| | 99 | 140 | | out exit, |
| | 99 | 141 | | out startContained, |
| | 99 | 142 | | out endContainedStrict); |
| | | 143 | | |
| | | 144 | | internal static bool TryGetCenteredInterval( |
| | | 145 | | FixedSegment query, |
| | | 146 | | Vector3d center, |
| | | 147 | | Vector3d baseToApexDirection, |
| | | 148 | | Fixed64 height, |
| | | 149 | | Fixed64 baseRadius, |
| | | 150 | | out Fixed64 entry, |
| | | 151 | | out Fixed64 exit, |
| | | 152 | | out bool startContained, |
| | | 153 | | out bool endContainedStrict) => |
| | 3 | 154 | | TrySolve( |
| | 3 | 155 | | CreateCenteredData(query, center, baseToApexDirection, height, baseRadius), |
| | 3 | 156 | | Fixed64.One, |
| | 3 | 157 | | out entry, |
| | 3 | 158 | | out exit, |
| | 3 | 159 | | out startContained, |
| | 3 | 160 | | out endContainedStrict); |
| | | 161 | | |
| | | 162 | | internal static bool TryGetCenteredDistanceInterval( |
| | | 163 | | FixedSegment query, |
| | | 164 | | Vector3d center, |
| | | 165 | | Vector3d baseToApexDirection, |
| | | 166 | | Fixed64 height, |
| | | 167 | | Fixed64 baseRadius, |
| | | 168 | | Fixed64 totalDistance, |
| | | 169 | | out Fixed64 entry, |
| | | 170 | | out Fixed64 exit, |
| | | 171 | | out bool startContained, |
| | | 172 | | out bool endContainedStrict) => |
| | 17 | 173 | | TrySolve( |
| | 17 | 174 | | CreateCenteredData(query, center, baseToApexDirection, height, baseRadius), |
| | 17 | 175 | | totalDistance, |
| | 17 | 176 | | out entry, |
| | 17 | 177 | | out exit, |
| | 17 | 178 | | out startContained, |
| | 17 | 179 | | out endContainedStrict); |
| | | 180 | | |
| | | 181 | | internal static bool ContainsPointInApexCone( |
| | | 182 | | Vector3d point, |
| | | 183 | | Vector3d apex, |
| | | 184 | | Vector3d apexToBaseDirection, |
| | | 185 | | Fixed64 height, |
| | | 186 | | Fixed64 baseRadius, |
| | | 187 | | bool strict) |
| | | 188 | | { |
| | 8 | 189 | | Signed192 heightRaw = Signed192.Signed(height.m_rawValue); |
| | 8 | 190 | | Signed192 axisLengthSquared = GetDot( |
| | 8 | 191 | | apexToBaseDirection, |
| | 8 | 192 | | Vector3d.Zero, |
| | 8 | 193 | | apexToBaseDirection, |
| | 8 | 194 | | Vector3d.Zero); |
| | 8 | 195 | | bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared); |
| | 8 | 196 | | Signed192 axisProjection = GetDot( |
| | 8 | 197 | | point, |
| | 8 | 198 | | apex, |
| | 8 | 199 | | apexToBaseDirection, |
| | 8 | 200 | | Vector3d.Zero); |
| | 8 | 201 | | Signed192 axial = exactUnitAxis ? axisProjection : GetScaledRaw(axisProjection); |
| | 8 | 202 | | return ContainsPoint( |
| | 8 | 203 | | point, |
| | 8 | 204 | | apex, |
| | 8 | 205 | | heightRaw, |
| | 8 | 206 | | axisLengthSquared, |
| | 8 | 207 | | axisProjection, |
| | 8 | 208 | | axial, |
| | 8 | 209 | | exactUnitAxis ? GetScaledRaw(heightRaw) : GetAxisHeightProduct(axisLengthSquared, heightRaw), |
| | 8 | 210 | | One, |
| | 8 | 211 | | exactUnitAxis, |
| | 8 | 212 | | baseRadius, |
| | 8 | 213 | | strict); |
| | | 214 | | } |
| | | 215 | | |
| | | 216 | | internal static bool ContainsPointInCenteredCone( |
| | | 217 | | Vector3d point, |
| | | 218 | | Vector3d center, |
| | | 219 | | Vector3d baseToApexDirection, |
| | | 220 | | Fixed64 height, |
| | | 221 | | Fixed64 baseRadius, |
| | | 222 | | bool strict) |
| | | 223 | | { |
| | 11 | 224 | | Signed192 heightRaw = Signed192.Signed(height.m_rawValue); |
| | 11 | 225 | | Signed192 axisLengthSquared = GetDot( |
| | 11 | 226 | | baseToApexDirection, |
| | 11 | 227 | | Vector3d.Zero, |
| | 11 | 228 | | baseToApexDirection, |
| | 11 | 229 | | Vector3d.Zero); |
| | 11 | 230 | | bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared); |
| | 11 | 231 | | Signed192 axisProjection = GetDot(point, center, baseToApexDirection, Vector3d.Zero); |
| | 11 | 232 | | Signed192 maximumAxial = exactUnitAxis |
| | 11 | 233 | | ? GetScaledRaw(heightRaw) |
| | 11 | 234 | | : GetAxisHeightProduct(axisLengthSquared, heightRaw); |
| | 11 | 235 | | Signed192 axial = exactUnitAxis |
| | 11 | 236 | | ? WideArithmetic.SubtractSigned192(GetHalfScaledRaw(heightRaw), axisProjection) |
| | 11 | 237 | | : WideArithmetic.SubtractSigned192(maximumAxial, WideArithmetic.Double(GetScaledRaw(axisProjection))); |
| | 11 | 238 | | return ContainsPoint( |
| | 11 | 239 | | point, |
| | 11 | 240 | | center, |
| | 11 | 241 | | heightRaw, |
| | 11 | 242 | | axisLengthSquared, |
| | 11 | 243 | | axisProjection, |
| | 11 | 244 | | axial, |
| | 11 | 245 | | exactUnitAxis ? maximumAxial : WideArithmetic.Double(maximumAxial), |
| | 11 | 246 | | exactUnitAxis ? One : Four, |
| | 11 | 247 | | exactUnitAxis, |
| | 11 | 248 | | baseRadius, |
| | 11 | 249 | | strict); |
| | | 250 | | } |
| | | 251 | | |
| | | 252 | | private static bool ContainsPoint( |
| | | 253 | | Vector3d point, |
| | | 254 | | Vector3d origin, |
| | | 255 | | Signed192 heightRaw, |
| | | 256 | | Signed192 axisLengthSquared, |
| | | 257 | | Signed192 axisProjection, |
| | | 258 | | Signed192 axial, |
| | | 259 | | Signed192 maximumAxial, |
| | | 260 | | Signed192 radialScale, |
| | | 261 | | bool exactUnitAxis, |
| | | 262 | | Fixed64 baseRadius, |
| | | 263 | | bool strict) |
| | | 264 | | { |
| | 19 | 265 | | Signed192 distanceSquared = GetDot(point, origin, point, origin); |
| | 19 | 266 | | Signed320 radial = GetRadialTerm(distanceSquared, axisProjection, axisLengthSquared); |
| | 19 | 267 | | Signed320 heightSquared = WideArithmetic.MultiplySigned192(heightRaw, heightRaw); |
| | 19 | 268 | | Signed192 radiusRaw = Signed192.Signed(baseRadius.m_rawValue); |
| | 19 | 269 | | Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radiusRaw, radiusRaw); |
| | 19 | 270 | | Signed576 polynomial = SubtractConeTerms( |
| | 19 | 271 | | heightSquared, |
| | 19 | 272 | | radial, |
| | 19 | 273 | | axisLengthSquared, |
| | 19 | 274 | | radialScale, |
| | 19 | 275 | | exactUnitAxis, |
| | 19 | 276 | | radiusSquared, |
| | 19 | 277 | | WideArithmetic.MultiplySigned192(axial, axial)); |
| | 19 | 278 | | return IsContained(axial, polynomial, maximumAxial, strict); |
| | | 279 | | } |
| | | 280 | | |
| | | 281 | | private static bool TrySolve( |
| | | 282 | | ConeData data, |
| | | 283 | | Fixed64 outputScale, |
| | | 284 | | out Fixed64 entry, |
| | | 285 | | out Fixed64 exit, |
| | | 286 | | out bool startContained, |
| | | 287 | | out bool endContainedStrict) |
| | | 288 | | { |
| | 162 | 289 | | startContained = IsContained( |
| | 162 | 290 | | data.StartAxial, |
| | 162 | 291 | | data.Constant, |
| | 162 | 292 | | data.MaximumAxial, |
| | 162 | 293 | | strict: false); |
| | 162 | 294 | | Signed192 endAxial = WideArithmetic.AddSigned192(data.StartAxial, data.AxialVelocity); |
| | 162 | 295 | | endContainedStrict = false; |
| | | 296 | | |
| | 162 | 297 | | if (!TryGetAxialInterval(data, out RationalBound lower, out RationalBound upper)) |
| | | 298 | | { |
| | 20 | 299 | | entry = default; |
| | 20 | 300 | | exit = default; |
| | 20 | 301 | | return false; |
| | | 302 | | } |
| | | 303 | | |
| | 142 | 304 | | if (endAxial.Sign > 0 |
| | 142 | 305 | | && WideArithmetic.SubtractSigned192(endAxial, data.MaximumAxial).Sign < 0) |
| | | 306 | | { |
| | 82 | 307 | | endContainedStrict = Evaluate(data, One, One).Sign < 0; |
| | | 308 | | } |
| | | 309 | | |
| | 142 | 310 | | return TrySolveBoundedPolynomial(data, lower, upper, outputScale, out entry, out exit); |
| | | 311 | | } |
| | | 312 | | |
| | | 313 | | private static bool TrySolveBoundedPolynomial( |
| | | 314 | | ConeData data, |
| | | 315 | | RationalBound lower, |
| | | 316 | | RationalBound upper, |
| | | 317 | | Fixed64 outputScale, |
| | | 318 | | out Fixed64 entry, |
| | | 319 | | out Fixed64 exit) |
| | | 320 | | { |
| | 2400 | 321 | | Signed832 lowerValue = Evaluate(data, lower.Numerator, lower.Denominator); |
| | 2400 | 322 | | Signed832 upperValue = Evaluate(data, upper.Numerator, upper.Denominator); |
| | 2400 | 323 | | bool lowerContained = lowerValue.Sign <= 0; |
| | 2400 | 324 | | bool upperContained = upperValue.Sign <= 0; |
| | | 325 | | |
| | 2400 | 326 | | if (data.Coefficient.IsZero) |
| | | 327 | | { |
| | 251 | 328 | | if (data.Projection.IsZero) |
| | | 329 | | { |
| | 241 | 330 | | if (!lowerContained) |
| | | 331 | | { |
| | 166 | 332 | | entry = default; |
| | 166 | 333 | | exit = default; |
| | 166 | 334 | | return false; |
| | | 335 | | } |
| | | 336 | | |
| | 75 | 337 | | entry = Round(lower, outputScale); |
| | 75 | 338 | | exit = Round(upper, outputScale); |
| | 75 | 339 | | return true; |
| | | 340 | | } |
| | | 341 | | |
| | 10 | 342 | | if (lowerContained && upperContained) |
| | | 343 | | { |
| | 1 | 344 | | entry = Round(lower, outputScale); |
| | 1 | 345 | | exit = Round(upper, outputScale); |
| | 1 | 346 | | return true; |
| | | 347 | | } |
| | 9 | 348 | | if (!lowerContained && !upperContained) |
| | | 349 | | { |
| | 7 | 350 | | entry = default; |
| | 7 | 351 | | exit = default; |
| | 7 | 352 | | return false; |
| | | 353 | | } |
| | | 354 | | |
| | 2 | 355 | | Fixed64 root = RoundLinearRoot(data, outputScale); |
| | 2 | 356 | | entry = lowerContained ? Round(lower, outputScale) : root; |
| | 2 | 357 | | exit = upperContained ? Round(upper, outputScale) : root; |
| | 2 | 358 | | return true; |
| | | 359 | | } |
| | | 360 | | |
| | 2149 | 361 | | if (lowerContained && upperContained) |
| | | 362 | | { |
| | 19 | 363 | | entry = Round(lower, outputScale); |
| | 19 | 364 | | exit = Round(upper, outputScale); |
| | 19 | 365 | | return true; |
| | | 366 | | } |
| | | 367 | | |
| | 2130 | 368 | | bool opensUp = data.Coefficient.Sign > 0; |
| | 2130 | 369 | | if (!opensUp && !lowerContained && !upperContained) |
| | | 370 | | { |
| | 7 | 371 | | entry = default; |
| | 7 | 372 | | exit = default; |
| | 7 | 373 | | return false; |
| | | 374 | | } |
| | | 375 | | |
| | 2123 | 376 | | if (opensUp |
| | 2123 | 377 | | && ((!lowerContained && EvaluateDerivative(data, lower).Sign >= 0) |
| | 2123 | 378 | | || (!upperContained && EvaluateDerivative(data, upper).Sign <= 0))) |
| | | 379 | | { |
| | 450 | 380 | | entry = default; |
| | 450 | 381 | | exit = default; |
| | 450 | 382 | | return false; |
| | | 383 | | } |
| | | 384 | | |
| | 1673 | 385 | | ConeData normalized = opensUp ? data : data.NegatedPolynomial(); |
| | 1673 | 386 | | Signed832 discriminant = WideArithmetic.SubtractSigned832( |
| | 1673 | 387 | | WideArithmetic.MultiplySigned576ToSigned832(normalized.Projection, normalized.Projection), |
| | 1673 | 388 | | WideArithmetic.MultiplySigned576ToSigned832(normalized.Coefficient, normalized.Constant)); |
| | 1673 | 389 | | if (discriminant.Sign < 0) |
| | | 390 | | { |
| | 523 | 391 | | entry = default; |
| | 523 | 392 | | exit = default; |
| | 523 | 393 | | return false; |
| | | 394 | | } |
| | | 395 | | |
| | 1150 | 396 | | Signed192 outputScaleRaw = Signed192.Signed(outputScale.m_rawValue); |
| | 1150 | 397 | | Signed192 outputScaleSquared = SquareRaw(outputScale.m_rawValue); |
| | 1150 | 398 | | Signed576 scaledSquareRoot = WideArithmetic.GetFloorSquareRootOfProduct( |
| | 1150 | 399 | | discriminant, |
| | 1150 | 400 | | outputScaleSquared); |
| | | 401 | | |
| | 1150 | 402 | | if (opensUp) |
| | | 403 | | { |
| | 1137 | 404 | | entry = lowerContained |
| | 1137 | 405 | | ? Round(lower, outputScale) |
| | 1137 | 406 | | : RoundLowerRoot(normalized, scaledSquareRoot, outputScaleRaw); |
| | 1137 | 407 | | exit = upperContained |
| | 1137 | 408 | | ? Round(upper, outputScale) |
| | 1137 | 409 | | : RoundUpperRoot(normalized, scaledSquareRoot, outputScaleRaw); |
| | 1137 | 410 | | return true; |
| | | 411 | | } |
| | | 412 | | |
| | 13 | 413 | | entry = lowerContained |
| | 13 | 414 | | ? Round(lower, outputScale) |
| | 13 | 415 | | : RoundUpperRoot(normalized, scaledSquareRoot, outputScaleRaw); |
| | 13 | 416 | | exit = upperContained |
| | 13 | 417 | | ? Round(upper, outputScale) |
| | 13 | 418 | | : RoundLowerRoot(normalized, scaledSquareRoot, outputScaleRaw); |
| | 13 | 419 | | return true; |
| | | 420 | | } |
| | | 421 | | |
| | | 422 | | private static Fixed64 RoundLinearRoot(ConeData data, Fixed64 outputScale) |
| | | 423 | | { |
| | 2 | 424 | | Signed192 outputScaleRaw = Signed192.Signed(outputScale.m_rawValue); |
| | 2 | 425 | | Signed576 numerator = WideArithmetic.MultiplySigned576( |
| | 2 | 426 | | WideArithmetic.SubtractSigned576(default, data.Constant), |
| | 2 | 427 | | outputScaleRaw); |
| | 2 | 428 | | Signed576 denominator = WideArithmetic.AddSigned576(data.Projection, data.Projection); |
| | 2 | 429 | | _ = Fixed64.TryGetSignedRawRatio(numerator, denominator, out Fixed64 root); |
| | 2 | 430 | | return root; |
| | | 431 | | } |
| | | 432 | | |
| | | 433 | | private static Fixed64 RoundLowerRoot( |
| | | 434 | | ConeData normalized, |
| | | 435 | | Signed576 scaledSquareRoot, |
| | | 436 | | Signed192 outputScaleRaw) |
| | | 437 | | { |
| | 1129 | 438 | | Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576( |
| | 1129 | 439 | | default, |
| | 1129 | 440 | | WideArithmetic.MultiplySigned576(normalized.Projection, outputScaleRaw)); |
| | 1129 | 441 | | Signed576 numerator = WideArithmetic.SubtractSigned576( |
| | 1129 | 442 | | negativeScaledProjection, |
| | 1129 | 443 | | scaledSquareRoot); |
| | 1129 | 444 | | _ = Fixed64.TryGetSignedRawRatio(numerator, normalized.Coefficient, out Fixed64 candidate); |
| | | 445 | | |
| | 1129 | 446 | | long upperRaw = candidate.m_rawValue; |
| | 1129 | 447 | | Signed192 upper = Signed192.Signed(upperRaw); |
| | 1129 | 448 | | Signed192 midpoint = WideArithmetic.SubtractSigned192( |
| | 1129 | 449 | | WideArithmetic.AddSigned192(upper, upper), |
| | 1129 | 450 | | One); |
| | 1129 | 451 | | Signed192 doubleScale = WideArithmetic.AddSigned192(outputScaleRaw, outputScaleRaw); |
| | 1129 | 452 | | Signed832 value = Evaluate(normalized, midpoint, doubleScale); |
| | 1129 | 453 | | if (value.IsZero) |
| | 1 | 454 | | return candidate; |
| | | 455 | | |
| | 1128 | 456 | | return Fixed64.FromRaw(value.Sign > 0 ? upperRaw : upperRaw - 1L); |
| | | 457 | | } |
| | | 458 | | |
| | | 459 | | private static Fixed64 RoundUpperRoot( |
| | | 460 | | ConeData normalized, |
| | | 461 | | Signed576 scaledSquareRoot, |
| | | 462 | | Signed192 outputScaleRaw) |
| | | 463 | | { |
| | 1123 | 464 | | Signed576 negativeScaledProjection = WideArithmetic.SubtractSigned576( |
| | 1123 | 465 | | default, |
| | 1123 | 466 | | WideArithmetic.MultiplySigned576(normalized.Projection, outputScaleRaw)); |
| | 1123 | 467 | | Signed576 numerator = WideArithmetic.AddSigned576( |
| | 1123 | 468 | | negativeScaledProjection, |
| | 1123 | 469 | | scaledSquareRoot); |
| | 1123 | 470 | | _ = Fixed64.TryGetSignedRawRatio(numerator, normalized.Coefficient, out Fixed64 candidate); |
| | | 471 | | |
| | 1123 | 472 | | long lowerRaw = candidate.m_rawValue; |
| | 1123 | 473 | | Signed192 lower = Signed192.Signed(lowerRaw); |
| | 1123 | 474 | | Signed192 midpoint = WideArithmetic.AddSigned192( |
| | 1123 | 475 | | WideArithmetic.AddSigned192(lower, lower), |
| | 1123 | 476 | | One); |
| | 1123 | 477 | | Signed192 doubleScale = WideArithmetic.AddSigned192(outputScaleRaw, outputScaleRaw); |
| | 1123 | 478 | | Signed832 value = Evaluate(normalized, midpoint, doubleScale); |
| | 1123 | 479 | | if (value.IsZero) |
| | 1 | 480 | | return candidate; |
| | | 481 | | |
| | 1122 | 482 | | return Fixed64.FromRaw(value.Sign <= 0 ? lowerRaw + 1L : lowerRaw); |
| | | 483 | | } |
| | | 484 | | |
| | | 485 | | private static bool TryGetAxialInterval( |
| | | 486 | | ConeData data, |
| | | 487 | | out RationalBound lower, |
| | | 488 | | out RationalBound upper) |
| | | 489 | | { |
| | 162 | 490 | | RationalBound zero = new(default, One); |
| | 162 | 491 | | RationalBound one = new(One, One); |
| | 162 | 492 | | lower = zero; |
| | 162 | 493 | | upper = one; |
| | | 494 | | |
| | 162 | 495 | | if (data.AxialVelocity.IsZero) |
| | | 496 | | { |
| | 77 | 497 | | return data.StartAxial.Sign >= 0 |
| | 77 | 498 | | && WideArithmetic.SubtractSigned192(data.StartAxial, data.MaximumAxial).Sign <= 0; |
| | | 499 | | } |
| | | 500 | | |
| | 85 | 501 | | RationalBound first = Normalize( |
| | 85 | 502 | | WideArithmetic.SubtractSigned192(default, data.StartAxial), |
| | 85 | 503 | | data.AxialVelocity); |
| | 85 | 504 | | RationalBound second = Normalize( |
| | 85 | 505 | | WideArithmetic.SubtractSigned192(data.MaximumAxial, data.StartAxial), |
| | 85 | 506 | | data.AxialVelocity); |
| | 85 | 507 | | if (Compare(first, second) > 0) |
| | 32 | 508 | | (first, second) = (second, first); |
| | | 509 | | |
| | 85 | 510 | | if (Compare(second, zero) < 0 || Compare(first, one) > 0) |
| | 3 | 511 | | return false; |
| | 82 | 512 | | if (Compare(first, zero) > 0) |
| | 41 | 513 | | lower = first; |
| | 82 | 514 | | if (Compare(second, one) < 0) |
| | 41 | 515 | | upper = second; |
| | 82 | 516 | | return true; |
| | | 517 | | } |
| | | 518 | | |
| | | 519 | | private static ConeData CreateApexData( |
| | | 520 | | FixedSegment query, |
| | | 521 | | Vector3d apex, |
| | | 522 | | Vector3d apexToBaseDirection, |
| | | 523 | | Fixed64 height, |
| | | 524 | | Fixed64 baseRadius) |
| | | 525 | | { |
| | 142 | 526 | | Signed192 heightRaw = Signed192.Signed(height.m_rawValue); |
| | 142 | 527 | | return CreateData( |
| | 142 | 528 | | query, |
| | 142 | 529 | | apex, |
| | 142 | 530 | | apexToBaseDirection, |
| | 142 | 531 | | heightRaw, |
| | 142 | 532 | | centered: false, |
| | 142 | 533 | | baseRadius); |
| | | 534 | | } |
| | | 535 | | |
| | | 536 | | private static ConeData CreateCenteredData( |
| | | 537 | | FixedSegment query, |
| | | 538 | | Vector3d center, |
| | | 539 | | Vector3d baseToApexDirection, |
| | | 540 | | Fixed64 height, |
| | | 541 | | Fixed64 baseRadius) |
| | | 542 | | { |
| | 20 | 543 | | Signed192 heightRaw = Signed192.Signed(height.m_rawValue); |
| | 20 | 544 | | return CreateData( |
| | 20 | 545 | | query, |
| | 20 | 546 | | center, |
| | 20 | 547 | | baseToApexDirection, |
| | 20 | 548 | | heightRaw, |
| | 20 | 549 | | centered: true, |
| | 20 | 550 | | baseRadius); |
| | | 551 | | } |
| | | 552 | | |
| | | 553 | | private static ConeData CreateData( |
| | | 554 | | FixedSegment query, |
| | | 555 | | Vector3d origin, |
| | | 556 | | Vector3d axisDirection, |
| | | 557 | | Signed192 heightRaw, |
| | | 558 | | bool centered, |
| | | 559 | | Fixed64 baseRadius) |
| | | 560 | | { |
| | 162 | 561 | | Signed192 startDistanceSquared = GetDot(query.Start, origin, query.Start, origin); |
| | 162 | 562 | | Signed192 startDirectionProjection = GetDot(query.Start, origin, query.End, query.Start); |
| | 162 | 563 | | Signed192 directionLengthSquared = GetDot(query.End, query.Start, query.End, query.Start); |
| | 162 | 564 | | Signed192 axisLengthSquared = GetDot(axisDirection, Vector3d.Zero, axisDirection, Vector3d.Zero); |
| | 162 | 565 | | bool exactUnitAxis = IsExactUnitAxis(axisLengthSquared); |
| | 162 | 566 | | Signed192 startAxisProjection = GetDot(query.Start, origin, axisDirection, Vector3d.Zero); |
| | 162 | 567 | | Signed192 directionAxisProjection = GetDot(query.End, query.Start, axisDirection, Vector3d.Zero); |
| | 162 | 568 | | Signed192 maximumAxisHeight = exactUnitAxis |
| | 162 | 569 | | ? GetScaledRaw(heightRaw) |
| | 162 | 570 | | : GetAxisHeightProduct(axisLengthSquared, heightRaw); |
| | | 571 | | Signed192 startAxial; |
| | | 572 | | Signed192 axialVelocity; |
| | | 573 | | Signed192 maximumAxial; |
| | | 574 | | Signed192 radialScale; |
| | 162 | 575 | | if (exactUnitAxis) |
| | | 576 | | { |
| | 155 | 577 | | startAxial = centered |
| | 155 | 578 | | ? WideArithmetic.SubtractSigned192(GetHalfScaledRaw(heightRaw), startAxisProjection) |
| | 155 | 579 | | : startAxisProjection; |
| | 155 | 580 | | axialVelocity = centered |
| | 155 | 581 | | ? WideArithmetic.SubtractSigned192(default, directionAxisProjection) |
| | 155 | 582 | | : directionAxisProjection; |
| | 155 | 583 | | maximumAxial = maximumAxisHeight; |
| | 155 | 584 | | radialScale = One; |
| | | 585 | | } |
| | | 586 | | else |
| | | 587 | | { |
| | 7 | 588 | | Signed192 scaledStartAxisProjection = GetScaledRaw(startAxisProjection); |
| | 7 | 589 | | Signed192 scaledDirectionAxisProjection = GetScaledRaw(directionAxisProjection); |
| | 7 | 590 | | startAxial = centered |
| | 7 | 591 | | ? WideArithmetic.SubtractSigned192(maximumAxisHeight, WideArithmetic.Double(scaledStartAxisProjection)) |
| | 7 | 592 | | : scaledStartAxisProjection; |
| | 7 | 593 | | axialVelocity = centered |
| | 7 | 594 | | ? WideArithmetic.SubtractSigned192(default, WideArithmetic.Double(scaledDirectionAxisProjection)) |
| | 7 | 595 | | : scaledDirectionAxisProjection; |
| | 7 | 596 | | maximumAxial = centered |
| | 7 | 597 | | ? WideArithmetic.Double(maximumAxisHeight) |
| | 7 | 598 | | : maximumAxisHeight; |
| | 7 | 599 | | radialScale = centered ? Four : One; |
| | | 600 | | } |
| | | 601 | | |
| | 162 | 602 | | Signed320 radialCoefficient = GetRadialTerm( |
| | 162 | 603 | | directionLengthSquared, |
| | 162 | 604 | | directionAxisProjection, |
| | 162 | 605 | | axisLengthSquared); |
| | 162 | 606 | | Signed320 radialProjection = GetRadialTerm( |
| | 162 | 607 | | startDirectionProjection, |
| | 162 | 608 | | startAxisProjection, |
| | 162 | 609 | | directionAxisProjection, |
| | 162 | 610 | | axisLengthSquared); |
| | 162 | 611 | | Signed320 radialConstant = GetRadialTerm( |
| | 162 | 612 | | startDistanceSquared, |
| | 162 | 613 | | startAxisProjection, |
| | 162 | 614 | | axisLengthSquared); |
| | 162 | 615 | | Signed320 heightSquared = WideArithmetic.MultiplySigned192(heightRaw, heightRaw); |
| | 162 | 616 | | Signed192 radiusRaw = Signed192.Signed(baseRadius.m_rawValue); |
| | 162 | 617 | | Signed320 radiusSquared = WideArithmetic.MultiplySigned192(radiusRaw, radiusRaw); |
| | 162 | 618 | | Signed320 axialVelocitySquared = WideArithmetic.MultiplySigned192(axialVelocity, axialVelocity); |
| | 162 | 619 | | Signed320 axialProduct = WideArithmetic.MultiplySigned192(startAxial, axialVelocity); |
| | 162 | 620 | | Signed320 startAxialSquared = WideArithmetic.MultiplySigned192(startAxial, startAxial); |
| | | 621 | | |
| | 162 | 622 | | return new ConeData( |
| | 162 | 623 | | startAxial, |
| | 162 | 624 | | axialVelocity, |
| | 162 | 625 | | maximumAxial, |
| | 162 | 626 | | SubtractConeTerms( |
| | 162 | 627 | | heightSquared, radialCoefficient, axisLengthSquared, radialScale, |
| | 162 | 628 | | exactUnitAxis, |
| | 162 | 629 | | radiusSquared, axialVelocitySquared), |
| | 162 | 630 | | SubtractConeTerms( |
| | 162 | 631 | | heightSquared, radialProjection, axisLengthSquared, radialScale, |
| | 162 | 632 | | exactUnitAxis, |
| | 162 | 633 | | radiusSquared, axialProduct), |
| | 162 | 634 | | SubtractConeTerms( |
| | 162 | 635 | | heightSquared, radialConstant, axisLengthSquared, radialScale, |
| | 162 | 636 | | exactUnitAxis, |
| | 162 | 637 | | radiusSquared, startAxialSquared)); |
| | | 638 | | } |
| | | 639 | | |
| | | 640 | | private static Signed320 GetRadialTerm( |
| | | 641 | | Signed192 squaredLength, |
| | | 642 | | Signed192 axisProjection, |
| | | 643 | | Signed192 axisLengthSquared) => |
| | 343 | 644 | | WideArithmetic.SubtractSigned320( |
| | 343 | 645 | | WideArithmetic.MultiplySigned192(squaredLength, axisLengthSquared), |
| | 343 | 646 | | WideArithmetic.MultiplySigned192(axisProjection, axisProjection)); |
| | | 647 | | |
| | | 648 | | private static Signed320 GetRadialTerm( |
| | | 649 | | Signed192 dot, |
| | | 650 | | Signed192 startAxisProjection, |
| | | 651 | | Signed192 directionAxisProjection, |
| | | 652 | | Signed192 axisLengthSquared) => |
| | 162 | 653 | | WideArithmetic.SubtractSigned320( |
| | 162 | 654 | | WideArithmetic.MultiplySigned192(dot, axisLengthSquared), |
| | 162 | 655 | | WideArithmetic.MultiplySigned192(startAxisProjection, directionAxisProjection)); |
| | | 656 | | |
| | | 657 | | private static Signed576 SubtractConeTerms( |
| | | 658 | | Signed320 heightSquared, |
| | | 659 | | Signed320 radialTerm, |
| | | 660 | | Signed192 axisLengthSquared, |
| | | 661 | | Signed192 radialScale, |
| | | 662 | | bool exactUnitAxis, |
| | | 663 | | Signed320 radiusSquared, |
| | | 664 | | Signed320 axialTerm) |
| | | 665 | | { |
| | 505 | 666 | | if (exactUnitAxis) |
| | | 667 | | { |
| | 479 | 668 | | return WideArithmetic.SubtractSigned576( |
| | 479 | 669 | | WideArithmetic.MultiplySigned320(heightSquared, radialTerm), |
| | 479 | 670 | | WideArithmetic.MultiplySigned320(radiusSquared, axialTerm)); |
| | | 671 | | } |
| | | 672 | | |
| | 26 | 673 | | Signed576 radial = WideArithmetic.MultiplySigned576( |
| | 26 | 674 | | WideArithmetic.MultiplySigned576( |
| | 26 | 675 | | WideArithmetic.MultiplySigned320(heightSquared, radialTerm), |
| | 26 | 676 | | axisLengthSquared), |
| | 26 | 677 | | radialScale); |
| | 26 | 678 | | Signed576 axial = WideArithmetic.MultiplySigned320(radiusSquared, axialTerm); |
| | 26 | 679 | | return WideArithmetic.SubtractSigned576(radial, axial); |
| | | 680 | | } |
| | | 681 | | |
| | | 682 | | private static Signed832 Evaluate(ConeData data, Signed192 numerator, Signed192 denominator) |
| | | 683 | | { |
| | | 684 | | // Rigid-frame coefficients have fewer than 390 magnitude bits after |
| | | 685 | | // their common quaternion-denominator factor is removed. Clipped |
| | | 686 | | // rational bounds have at most 132-bit magnitudes, so every homogenized |
| | | 687 | | // term and their sum fit below 656 bits. Signed832 also retains the |
| | | 688 | | // wider legacy conic intermediates without the former eleven-word |
| | | 689 | | // truncation. |
| | 7394 | 690 | | Signed320 numeratorSquared = WideArithmetic.MultiplySigned192(numerator, numerator); |
| | 7394 | 691 | | Signed320 numeratorDenominator = WideArithmetic.MultiplySigned192(numerator, denominator); |
| | 7394 | 692 | | Signed320 denominatorSquared = WideArithmetic.MultiplySigned192(denominator, denominator); |
| | 7394 | 693 | | Signed832 first = WideArithmetic.MultiplySigned576ToSigned832(data.Coefficient, numeratorSquared); |
| | 7394 | 694 | | Signed832 second = WideArithmetic.MultiplySigned576ToSigned832(data.Projection, numeratorDenominator); |
| | 7394 | 695 | | Signed832 third = WideArithmetic.MultiplySigned576ToSigned832(data.Constant, denominatorSquared); |
| | 7394 | 696 | | return WideArithmetic.AddSigned832( |
| | 7394 | 697 | | WideArithmetic.AddSigned832(first, WideArithmetic.AddSigned832(second, second)), |
| | 7394 | 698 | | third); |
| | | 699 | | } |
| | | 700 | | |
| | | 701 | | private static Signed832 EvaluateDerivative(ConeData data, RationalBound bound) => |
| | 3825 | 702 | | WideArithmetic.AddSigned832( |
| | 3825 | 703 | | WideArithmetic.MultiplySigned576ToSigned832( |
| | 3825 | 704 | | data.Coefficient, |
| | 3825 | 705 | | Signed320.ExtendValue(bound.Numerator)), |
| | 3825 | 706 | | WideArithmetic.MultiplySigned576ToSigned832( |
| | 3825 | 707 | | data.Projection, |
| | 3825 | 708 | | Signed320.ExtendValue(bound.Denominator))); |
| | | 709 | | |
| | | 710 | | private static bool IsContained( |
| | | 711 | | Signed192 axial, |
| | | 712 | | Signed576 polynomial, |
| | | 713 | | Signed192 maximumAxial, |
| | | 714 | | bool strict) => |
| | 181 | 715 | | IsContained(axial, polynomial.Sign, maximumAxial, strict); |
| | | 716 | | |
| | | 717 | | private static bool IsContained( |
| | | 718 | | Signed192 axial, |
| | | 719 | | int polynomialSign, |
| | | 720 | | Signed192 maximumAxial, |
| | | 721 | | bool strict) |
| | | 722 | | { |
| | 181 | 723 | | int maximumSign = WideArithmetic.SubtractSigned192(axial, maximumAxial).Sign; |
| | 181 | 724 | | return strict |
| | 181 | 725 | | ? axial.Sign > 0 && maximumSign < 0 && polynomialSign < 0 |
| | 181 | 726 | | : axial.Sign >= 0 && maximumSign <= 0 && polynomialSign <= 0; |
| | | 727 | | } |
| | | 728 | | |
| | | 729 | | private static Signed192 GetScaledRaw(Signed192 value) => |
| | 215 | 730 | | new((value.High << FixedMath.SHIFT_AMOUNT_I) | (value.Middle >> FixedMath.SHIFT_AMOUNT_I), |
| | 215 | 731 | | (value.Middle << FixedMath.SHIFT_AMOUNT_I) | (value.Low >> FixedMath.SHIFT_AMOUNT_I), |
| | 215 | 732 | | value.Low << FixedMath.SHIFT_AMOUNT_I); |
| | | 733 | | |
| | | 734 | | private static Signed192 GetAxisHeightProduct( |
| | | 735 | | Signed192 axisLengthSquared, |
| | | 736 | | Signed192 heightRaw) |
| | | 737 | | { |
| | 12 | 738 | | Signed320 product = WideArithmetic.MultiplySigned192(axisLengthSquared, heightRaw); |
| | | 739 | | // IsNormalized bounds the positive axis square near 2^64; multiplying |
| | | 740 | | // by a positive Fixed64 raw height therefore occupies fewer than 129 bits. |
| | 12 | 741 | | return new Signed192(product.Word2, product.Word1, product.Word0); |
| | | 742 | | } |
| | | 743 | | |
| | | 744 | | private static Signed192 GetHalfScaledRaw(Signed192 value) |
| | | 745 | | { |
| | 27 | 746 | | Signed192 scaled = GetScaledRaw(value); |
| | 27 | 747 | | ulong high = scaled.High; |
| | 27 | 748 | | ulong middle = scaled.Middle; |
| | 27 | 749 | | ulong low = scaled.Low; |
| | 27 | 750 | | WideArithmetic.ShiftRightOne(ref high, ref middle, ref low); |
| | 27 | 751 | | return new Signed192(high, middle, low); |
| | | 752 | | } |
| | | 753 | | |
| | | 754 | | private static bool IsExactUnitAxis(Signed192 axisLengthSquared) => |
| | 181 | 755 | | axisLengthSquared.High == AxisScaleSquared.High |
| | 181 | 756 | | && axisLengthSquared.Middle == AxisScaleSquared.Middle |
| | 181 | 757 | | && axisLengthSquared.Low == AxisScaleSquared.Low; |
| | | 758 | | |
| | | 759 | | private static Signed192 SquareRaw(long raw) |
| | | 760 | | { |
| | 1150 | 761 | | ulong magnitude = (ulong)raw; |
| | 1150 | 762 | | Fixed64.Multiply64To128(magnitude, magnitude, out ulong high, out ulong low); |
| | 1150 | 763 | | return new Signed192(0UL, high, low); |
| | | 764 | | } |
| | | 765 | | |
| | | 766 | | private static RationalBound Normalize(Signed192 numerator, Signed192 denominator) |
| | | 767 | | { |
| | 170 | 768 | | if (denominator.Sign >= 0) |
| | 106 | 769 | | return new RationalBound(numerator, denominator); |
| | | 770 | | |
| | 64 | 771 | | return new RationalBound( |
| | 64 | 772 | | WideArithmetic.SubtractSigned192(default, numerator), |
| | 64 | 773 | | WideArithmetic.SubtractSigned192(default, denominator)); |
| | | 774 | | } |
| | | 775 | | |
| | | 776 | | private static int Compare(RationalBound left, RationalBound right) => |
| | 418 | 777 | | WideArithmetic.MultiplySubtract( |
| | 418 | 778 | | left.Numerator, |
| | 418 | 779 | | right.Denominator, |
| | 418 | 780 | | right.Numerator, |
| | 418 | 781 | | left.Denominator).Sign; |
| | | 782 | | |
| | | 783 | | private static Fixed64 Round(RationalBound value, Fixed64 outputScale) |
| | | 784 | | { |
| | 240 | 785 | | Signed320 numerator = WideArithmetic.MultiplySigned192( |
| | 240 | 786 | | value.Numerator, |
| | 240 | 787 | | Signed192.Signed(outputScale.m_rawValue)); |
| | 240 | 788 | | _ = Fixed64.TryGetSignedRawRatio( |
| | 240 | 789 | | Signed576.ExtendValue(numerator), |
| | 240 | 790 | | Signed576.ExtendValue(Signed320.ExtendValue(value.Denominator)), |
| | 240 | 791 | | out Fixed64 result); |
| | 240 | 792 | | return result; |
| | | 793 | | } |
| | | 794 | | |
| | | 795 | | private static Signed192 GetDot( |
| | | 796 | | Vector3d leftEnd, |
| | | 797 | | Vector3d leftStart, |
| | | 798 | | Vector3d rightEnd, |
| | | 799 | | Vector3d rightStart) => |
| | 1029 | 800 | | WideGeometry.GetDifferenceDotProduct3D( |
| | 1029 | 801 | | leftEnd.X, leftStart.X, leftEnd.Y, leftStart.Y, leftEnd.Z, leftStart.Z, |
| | 1029 | 802 | | rightEnd.X, rightStart.X, rightEnd.Y, rightStart.Y, rightEnd.Z, rightStart.Z); |
| | | 803 | | |
| | | 804 | | internal static int EvaluateBoundedUnitPolynomialSign( |
| | | 805 | | Signed576 coefficient, |
| | | 806 | | Signed576 projection, |
| | | 807 | | Signed576 constant, |
| | | 808 | | Signed192 numerator, |
| | | 809 | | Signed192 denominator) => |
| | 64 | 810 | | Evaluate( |
| | 64 | 811 | | new ConeData( |
| | 64 | 812 | | default, |
| | 64 | 813 | | default, |
| | 64 | 814 | | default, |
| | 64 | 815 | | coefficient, |
| | 64 | 816 | | projection, |
| | 64 | 817 | | constant), |
| | 64 | 818 | | numerator, |
| | 64 | 819 | | denominator).Sign; |
| | | 820 | | |
| | | 821 | | internal static int EvaluateBoundedUnitPolynomialDerivativeSign( |
| | | 822 | | Signed576 coefficient, |
| | | 823 | | Signed576 projection, |
| | | 824 | | Signed192 numerator, |
| | | 825 | | Signed192 denominator) => |
| | 64 | 826 | | EvaluateDerivative( |
| | 64 | 827 | | new ConeData( |
| | 64 | 828 | | default, |
| | 64 | 829 | | default, |
| | 64 | 830 | | default, |
| | 64 | 831 | | coefficient, |
| | 64 | 832 | | projection, |
| | 64 | 833 | | default), |
| | 64 | 834 | | new RationalBound(numerator, denominator)).Sign; |
| | | 835 | | |
| | | 836 | | internal static bool TrySolveBoundedUnitPolynomial( |
| | | 837 | | Signed576 coefficient, |
| | | 838 | | Signed576 projection, |
| | | 839 | | Signed576 constant, |
| | | 840 | | Signed192 lowerNumerator, |
| | | 841 | | Signed192 lowerDenominator, |
| | | 842 | | Signed192 upperNumerator, |
| | | 843 | | Signed192 upperDenominator, |
| | | 844 | | Fixed64 outputScale, |
| | | 845 | | out Fixed64 entry, |
| | | 846 | | out Fixed64 exit) => |
| | 396 | 847 | | TrySolveBoundedPolynomial( |
| | 396 | 848 | | new ConeData( |
| | 396 | 849 | | default, |
| | 396 | 850 | | default, |
| | 396 | 851 | | default, |
| | 396 | 852 | | coefficient, |
| | 396 | 853 | | projection, |
| | 396 | 854 | | constant), |
| | 396 | 855 | | new RationalBound(lowerNumerator, lowerDenominator), |
| | 396 | 856 | | new RationalBound(upperNumerator, upperDenominator), |
| | 396 | 857 | | outputScale, |
| | 396 | 858 | | out entry, |
| | 396 | 859 | | out exit); |
| | | 860 | | } |