( ce: ComputeEngine, ops: ReadonlyArray<Expression>, mode: 'Min' | 'Max' | 'Supremum' | 'Infimum' )
| 2753 | // sign). `floor(x + 0.5)` reproduces `Math.round`'s tie-breaking |
| 2754 | // exactly, keeping both lanes in agreement. |
| 2755 | (a, b) => a.sub(b.mul(a.div(b).add(0.5).floor())) |
| 2756 | ), |
| 2757 | }, |
| 2758 | |
| 2759 | Round: { |
| 2760 | description: |
| 2761 | 'Rounds a number to the nearest integer, or (with a precision argument) to `n` decimal places.', |
| 2762 | complexity: 1250, |
| 2763 | broadcastable: true, |
| 2764 | // Optional precision arg (Desmos/spreadsheet `round(x, n)`): round to `n` |
| 2765 | // decimal places. Without it, rounds to the nearest integer. |
| 2766 | signature: '(number, integer?) -> number', |
| 2767 | type: ([x, n]) => |
| 2768 | n === undefined |
| 2769 | ? roundingFunctionType(x) |
| 2770 | : // With a precision arg the result is generally non-integer; keep |
| 2771 | // the complex/non-finite/NaN classification but never claim integer. |
| 2772 | x.isFinite === true && x.isReal === true |
| 2773 | ? 'finite_real' |
| 2774 | : roundingFunctionType(x), |
| 2775 | sgn: ([x, n]) => { |
| 2776 | // Only reason about the sign in the single-argument (round-to-integer) |
| 2777 | // case; a precision arg rescales the value and the interval reasoning |
| 2778 | // below no longer holds. |
| 2779 | if (n !== undefined) return undefined; |
| 2780 | if (x.isNaN) return 'unsigned'; |
| 2781 | // The evaluate handler rounds halves AWAY from zero in every lane |
| 2782 | // (Round(-1/2) = -1); Math.round ties toward +∞, so negate-and-round |
| 2783 | // for negative reals or `.sgn` and `.evaluate()` disagree at -0.5. |
| 2784 | if (isNumber(x)) |
| 2785 | return x.im! >= 0.5 || x.im! <= -0.5 |
| 2786 | ? 'unsigned' |
| 2787 | : numberSgn(x.re < 0 ? -Math.round(-x.re) : Math.round(x.re)); |
| 2788 | if (x.isGreaterEqual(0.5)) return 'positive'; |
| 2789 | if (x.isLessEqual(-0.5)) return 'negative'; |
| 2790 | if (x.isLess(0.5) && x.isGreater(-0.5)) return 'zero'; |
| 2791 | if (x.isNonNegative) return 'non-negative'; |
| 2792 | if (x.isNonPositive) return 'non-positive'; |
| 2793 | return undefined; |
| 2794 | }, |
| 2795 | evaluate: ([x, n], { engine: ce }) => { |
| 2796 | const roundToInteger = (v: Expression) => |
| 2797 | apply( |
no test coverage detected