(u: Expression)
| 1077 | // raw relational heads (older Rubi guards; symbolic operands ⇒ false) |
| 1078 | Less: (args, ctx) => cmpChain(args, ctx, (a, b) => a < b), |
| 1079 | Greater: (args, ctx) => cmpChain(args, ctx, (a, b) => a > b), |
| 1080 | LessEqual: (args, ctx) => cmpChain(args, ctx, (a, b) => a <= b), |
| 1081 | GreaterEqual: (args, ctx) => cmpChain(args, ctx, (a, b) => a >= b), |
| 1082 | Equal: (args, ctx) => cmpChain(args, ctx, (a, b) => a === b), |
| 1083 | Unequal: (args, ctx) => cmpChain(args, ctx, (a, b) => a !== b), |
| 1084 | }; |
| 1085 | |
| 1086 | // IntegerQ-style helpers over built expressions (IntBinomialQ/IntQuadraticQ) |
| 1087 | function intQE(e: Expression): boolean { |
| 1088 | return isLiteralInteger(e.evaluate()); |
| 1089 | } |
| 1090 | function intsQE(...es: Expression[]): boolean { |
| 1091 | return es.every(intQE); |
| 1092 | } |
| 1093 | function igtQE(e: Expression, k: number): boolean { |
| 1094 | const ev = e.evaluate(); |
| 1095 | return isLiteralInteger(ev) && (realNum(ev) ?? -Infinity) > k; |
| 1096 | } |
| 1097 | function eqNum(e: Expression, k: number): boolean { |
| 1098 | const r = realNum(e.evaluate()); |
| 1099 | return r !== null ? r === k : zeroQ(e.sub(e.engine.number(k))); |
| 1100 | } |
| 1101 | |
| 1102 | /** Rubi QuadraticQ (scalar case): PolyQ[u,x,2] and not a pure c·x² */ |
| 1103 | function quadraticQX(u: Expression, x: string): boolean { |
| 1104 | const c = polyCoeffsX(u, x); |
| 1105 | if (c === null) return false; |
| 1106 | const t = trimZeros(c); |
| 1107 | if (t.length !== 3) return false; |
| 1108 | return !(t[0].isSame(0) && t[1].isSame(0)); |
| 1109 | } |
| 1110 | |
| 1111 | function cmpChain( |
| 1112 | args: Json[], |
| 1113 | ctx: Ctx, |
| 1114 | cmp: (a: number, b: number) => boolean |
| 1115 | ): boolean { |
| 1116 | // numeric first; fall back to simplification (symbolic ratios like |
| 1117 | // b/(b·c−a·d) after a normalization step can simplify to a number — |
| 1118 | // several Rubi guards rely on this to stop rule refiring), then to |
| 1119 | // multivariate rational collapse (nested-rational identities that |
no test coverage detected