( args: Json[], ctx: Ctx, cmp: (a: number, b: number) => boolean )
| 1041 | ), |
| 1042 | |
| 1043 | // --- WL structural/numeric builtins used in rule conditions --- |
| 1044 | |
| 1045 | SumQ: (args, ctx) => { |
| 1046 | const u = build(args[0], ctx); |
| 1047 | return u.operator === 'Add' || u.operator === 'Subtract'; |
| 1048 | }, |
| 1049 | NonsumQ: (args, ctx) => { |
| 1050 | const u = build(args[0], ctx); |
| 1051 | return u.operator !== 'Add' && u.operator !== 'Subtract'; |
| 1052 | }, |
| 1053 | // ProductQ[u] := u is a Times expression (IntegrationUtilityFunctions.m). |
| 1054 | ProductQ: (args, ctx) => build(args[0], ctx).operator === 'Multiply', |
| 1055 | // MemberQ[{e1,…,en}, u] := u is structurally one of the list elements. |
| 1056 | // Chapter-3 uses it to test whether a captured head F is an inverse |
| 1057 | // trig/hyperbolic function (ArcSin/ArcCos/ArcSinh/ArcCosh). |
| 1058 | MemberQ: (args, ctx) => { |
| 1059 | const list = args[0]; |
| 1060 | if (!Array.isArray(list) || list[0] !== 'List') return false; |
| 1061 | const elem = build(args[1], ctx); |
| 1062 | return (list as Json[]).slice(1).some((e) => build(e, ctx).isSame(elem)); |
| 1063 | }, |
| 1064 | // IntegralFreeQ[u] := u contains no inert integral node |
| 1065 | // (IntegrationUtilityFunctions.m: FreeQ of Int/Integral/Unintegrable/ |
| 1066 | // CannotIntegrate). Gates a Chapter-3 rule on its IntHide result closing. |
no test coverage detected