@@ -52,20 +52,24 @@ export const createSimplifyCore = /* #__PURE__ */ factory(name, dependencies, ({
5252 createUtil ( { FunctionNode, OperatorNode, SymbolNode } )
5353 /**
5454 * simplifyCore() performs single pass simplification suitable for
55- * applications requiring ultimate performance. In contrast, simplify()
56- * extends simplifyCore() with additional passes to provide deeper
57- * simplification.
55+ * applications requiring ultimate performance. To roughly summarize,
56+ * it handles cases along the lines of simplifyConstant() but where
57+ * knowledge of a single argument is sufficient to determine the value.
58+ * In contrast, simplify() extends simplifyCore() with additional passes
59+ * to provide deeper simplification (such as gathering like terms).
5860 *
5961 * Specifically, simplifyCore:
6062 *
6163 * * Converts all function calls with operator equivalents to their
6264 * operator forms.
6365 * * Removes operators or function calls that are guaranteed to have no
6466 * effect (such as unary '+').
65- * * Removes double unary '-' and '~ '
67+ * * Removes double unary '-', '~', and 'not '
6668 * * Eliminates addition/subtraction of 0 and multiplication/division/powers
6769 * by 1 or 0.
6870 * * Converts addition of a negation into subtraction.
71+ * * Eliminates logical operations with constant true or false leading
72+ * arguments.
6973 * * Puts constants on the left of a product, if multiplication is
7074 * considered commutative by the options (which is the default)
7175 *
@@ -146,26 +150,33 @@ export const createSimplifyCore = /* #__PURE__ */ factory(name, dependencies, ({
146150 if ( isOperatorNode ( node ) && node . isUnary ( ) ) {
147151 const a0 = simplifyCore ( node . args [ 0 ] , options )
148152
149- if ( node . op === '-' ) { // unary minus
150- if ( isOperatorNode ( a0 ) ) {
151- if ( a0 . isUnary ( ) && a0 . op === '-' ) {
152- return a0 . args [ 0 ]
153- } else if ( a0 . isBinary ( ) && a0 . fn === 'subtract' ) {
154- return new OperatorNode ( '-' , 'subtract' , [ a0 . args [ 1 ] , a0 . args [ 0 ] ] )
155- }
153+ if ( node . op === '~' ) { // bitwise not
154+ if ( isOperatorNode ( a0 ) && a0 . isUnary ( ) && a0 . op === '~' ) {
155+ return a0 . args [ 0 ]
156156 }
157- return new OperatorNode ( node . op , node . fn , [ a0 ] )
158157 }
159- if ( node . op === '~' ) { // bitwise not
158+ if ( node . op === 'not' ) { // logical not
159+ if ( isOperatorNode ( a0 ) && a0 . isUnary ( ) && a0 . op === 'not' ) {
160+ return a0 . args [ 0 ]
161+ }
162+ }
163+ let finish = true
164+ if ( node . op === '-' ) { // unary minus
160165 if ( isOperatorNode ( a0 ) ) {
161- if ( a0 . isUnary ( ) && a0 . op === '~' ) {
166+ if ( a0 . isBinary ( ) && a0 . fn === 'subtract' ) {
167+ node = new OperatorNode ( '-' , 'subtract' , [ a0 . args [ 1 ] , a0 . args [ 0 ] ] )
168+ finish = false // continue to process the new binary node
169+ }
170+ if ( a0 . isUnary ( ) && a0 . op === '-' ) {
162171 return a0 . args [ 0 ]
163172 }
164173 }
165174 }
166- } else if ( isOperatorNode ( node ) && node . isBinary ( ) ) {
175+ if ( finish ) return new OperatorNode ( node . op , node . fn , [ a0 ] )
176+ }
177+ if ( isOperatorNode ( node ) && node . isBinary ( ) ) {
167178 const a0 = simplifyCore ( node . args [ 0 ] , options )
168- const a1 = simplifyCore ( node . args [ 1 ] , options )
179+ let a1 = simplifyCore ( node . args [ 1 ] , options )
169180
170181 if ( node . op === '+' ) {
171182 if ( isConstantNode ( a0 ) && isZero ( a0 . value ) ) {
@@ -175,22 +186,24 @@ export const createSimplifyCore = /* #__PURE__ */ factory(name, dependencies, ({
175186 return a0
176187 }
177188 if ( isOperatorNode ( a1 ) && a1 . isUnary ( ) && a1 . op === '-' ) {
178- return new OperatorNode ( '-' , 'subtract' , [ a0 , a1 . args [ 0 ] ] )
189+ a1 = a1 . args [ 0 ]
190+ node = new OperatorNode ( '-' , 'subtract' , [ a0 , a1 ] )
191+ }
192+ }
193+ if ( node . op === '-' ) {
194+ if ( isOperatorNode ( a1 ) && a1 . isUnary ( ) && a1 . op === '-' ) {
195+ return simplifyCore (
196+ new OperatorNode ( '+' , 'add' , [ a0 , a1 . args [ 0 ] ] ) , options )
179197 }
180- return new OperatorNode ( node . op , node . fn , a1 ? [ a0 , a1 ] : [ a0 ] )
181- } else if ( node . op === '-' ) {
182198 if ( isConstantNode ( a0 ) && isZero ( a0 . value ) ) {
183- return new OperatorNode ( '-' , 'unaryMinus' , [ a1 ] )
199+ return simplifyCore ( new OperatorNode ( '-' , 'unaryMinus' , [ a1 ] ) )
184200 }
185201 if ( isConstantNode ( a1 ) && isZero ( a1 . value ) ) {
186202 return a0
187203 }
188- if ( isOperatorNode ( a1 ) && a1 . isUnary ( ) && a1 . op === '-' ) {
189- return simplifyCore (
190- new OperatorNode ( '+' , 'add' , [ a0 , a1 . args [ 0 ] ] ) , options )
191- }
192204 return new OperatorNode ( node . op , node . fn , [ a0 , a1 ] )
193- } else if ( node . op === '*' ) {
205+ }
206+ if ( node . op === '*' ) {
194207 if ( isConstantNode ( a0 ) ) {
195208 if ( isZero ( a0 . value ) ) {
196209 return node0
@@ -209,15 +222,17 @@ export const createSimplifyCore = /* #__PURE__ */ factory(name, dependencies, ({
209222 }
210223 }
211224 return new OperatorNode ( node . op , node . fn , [ a0 , a1 ] , node . implicit )
212- } else if ( node . op === '/' ) {
225+ }
226+ if ( node . op === '/' ) {
213227 if ( isConstantNode ( a0 ) && isZero ( a0 . value ) ) {
214228 return node0
215229 }
216230 if ( isConstantNode ( a1 ) && equal ( a1 . value , 1 ) ) {
217231 return a0
218232 }
219233 return new OperatorNode ( node . op , node . fn , [ a0 , a1 ] )
220- } else if ( node . op === '^' ) {
234+ }
235+ if ( node . op === '^' ) {
221236 if ( isConstantNode ( a1 ) ) {
222237 if ( isZero ( a1 . value ) ) {
223238 return node1
@@ -226,8 +241,27 @@ export const createSimplifyCore = /* #__PURE__ */ factory(name, dependencies, ({
226241 }
227242 }
228243 }
244+ if ( node . op === 'and' ) {
245+ if ( isConstantNode ( a0 ) ) {
246+ if ( a0 . value ) {
247+ return a1
248+ } else {
249+ return a0
250+ }
251+ }
252+ }
253+ if ( node . op === 'or' ) {
254+ if ( isConstantNode ( a0 ) ) {
255+ if ( a0 . value ) {
256+ return a0
257+ } else {
258+ return a1
259+ }
260+ }
261+ }
229262 return new OperatorNode ( node . op , node . fn , [ a0 , a1 ] )
230- } else if ( isOperatorNode ( node ) ) {
263+ }
264+ if ( isOperatorNode ( node ) ) {
231265 return new OperatorNode ( node . op , node . fn ,
232266 node . args . map ( a => simplifyCore ( a , options ) ) )
233267 }
0 commit comments