@@ -7,7 +7,7 @@ import type { BoxedExpression, RuleStep } from '../global-types';
77export function simplifySum ( x : BoxedExpression ) : RuleStep | undefined {
88 if ( x . operator !== 'Sum' ) return undefined ;
99
10- let body = x . op1 ;
10+ const body = x . op1 ;
1111 const limits = x . op2 ;
1212 if ( ! body || ! limits || limits . operator !== 'Limits' ) return undefined ;
1313
@@ -78,7 +78,10 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
7878 // = b(b+1)/2 - (a-1)a/2 = (b(b+1) - a(a-1)) / 2
7979 const a = lower ;
8080 const b = upper ;
81- const result = b . mul ( b . add ( ce . One ) ) . sub ( a . mul ( a . sub ( ce . One ) ) ) . div ( 2 ) ;
81+ const result = b
82+ . mul ( b . add ( ce . One ) )
83+ . sub ( a . mul ( a . sub ( ce . One ) ) )
84+ . div ( 2 ) ;
8285 return { value : result . simplify ( ) , because : 'triangular number' } ;
8386 }
8487
@@ -149,7 +152,10 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
149152 const result = ce . function ( 'Multiply' , [
150153 ce . function ( 'Power' , [ ce . number ( - 1 ) , b ] ) ,
151154 ce . function ( 'Floor' , [
152- ce . function ( 'Divide' , [ ce . function ( 'Add' , [ b , ce . One ] ) , ce . number ( 2 ) ] ) ,
155+ ce . function ( 'Divide' , [
156+ ce . function ( 'Add' , [ b , ce . One ] ) ,
157+ ce . number ( 2 ) ,
158+ ] ) ,
153159 ] ) ,
154160 ] ) ;
155161 return { value : result , because : 'alternating linear series' } ;
@@ -177,8 +183,7 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
177183 // c * n form - extract coefficient
178184 const coef = term . ops ! . filter ( ( op ) => op . symbol !== index ) ;
179185 if ( coef . length === term . ops ! . length - 1 ) {
180- const c =
181- coef . length === 1 ? coef [ 0 ] : ce . function ( 'Multiply' , coef ) ;
186+ const c = coef . length === 1 ? coef [ 0 ] : ce . function ( 'Multiply' , coef ) ;
182187 coefficient = coefficient ? coefficient . add ( c ) : c ;
183188 }
184189 } else {
@@ -274,10 +279,7 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
274279 let binomialN : BoxedExpression | null = null ;
275280
276281 for ( const op of body . ops ) {
277- if (
278- op . operator === 'Binomial' &&
279- op . op2 ?. symbol === index
280- ) {
282+ if ( op . operator === 'Binomial' && op . op2 ?. symbol === index ) {
281283 hasBinomial = true ;
282284 binomialN = op . op1 ?? null ;
283285 } else if (
@@ -303,16 +305,19 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
303305 for ( const op of body . ops ) {
304306 if ( op . symbol === index ) {
305307 hasIndex = true ;
306- } else if (
307- op . operator === 'Binomial' &&
308- op . op2 ?. symbol === index
309- ) {
308+ } else if ( op . operator === 'Binomial' && op . op2 ?. symbol === index ) {
310309 hasBinomial = true ;
311310 binomialN = op . op1 ?? null ;
312311 }
313312 }
314313
315- if ( hasIndex && hasBinomial && binomialN && upper . isSame ( binomialN ) && body . ops . length === 2 ) {
314+ if (
315+ hasIndex &&
316+ hasBinomial &&
317+ binomialN &&
318+ upper . isSame ( binomialN ) &&
319+ body . ops . length === 2
320+ ) {
316321 // n * 2^(n-1)
317322 const n = binomialN ;
318323 const result = ce . function ( 'Multiply' , [
@@ -328,18 +333,25 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
328333 hasBinomial = false ;
329334
330335 for ( const op of body . ops ) {
331- if ( op . operator === 'Power' && op . op1 ?. symbol === index && op . op2 ?. is ( 2 ) ) {
332- hasIndexSquared = true ;
333- } else if (
334- op . operator === 'Binomial' &&
335- op . op2 ?. symbol === index
336+ if (
337+ op . operator === 'Power' &&
338+ op . op1 ?. symbol === index &&
339+ op . op2 ?. is ( 2 )
336340 ) {
341+ hasIndexSquared = true ;
342+ } else if ( op . operator === 'Binomial' && op . op2 ?. symbol === index ) {
337343 hasBinomial = true ;
338344 binomialN = op . op1 ?? null ;
339345 }
340346 }
341347
342- if ( hasIndexSquared && hasBinomial && binomialN && upper . isSame ( binomialN ) && body . ops . length === 2 ) {
348+ if (
349+ hasIndexSquared &&
350+ hasBinomial &&
351+ binomialN &&
352+ upper . isSame ( binomialN ) &&
353+ body . ops . length === 2
354+ ) {
343355 // n(n+1) * 2^(n-2)
344356 const n = binomialN ;
345357 const result = ce . function ( 'Multiply' , [
@@ -356,18 +368,25 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
356368 hasBinomial = false ;
357369
358370 for ( const op of body . ops ) {
359- if ( op . operator === 'Power' && op . op1 ?. symbol === index && op . op2 ?. is ( 3 ) ) {
360- hasIndexCubed = true ;
361- } else if (
362- op . operator === 'Binomial' &&
363- op . op2 ?. symbol === index
371+ if (
372+ op . operator === 'Power' &&
373+ op . op1 ?. symbol === index &&
374+ op . op2 ?. is ( 3 )
364375 ) {
376+ hasIndexCubed = true ;
377+ } else if ( op . operator === 'Binomial' && op . op2 ?. symbol === index ) {
365378 hasBinomial = true ;
366379 binomialN = op . op1 ?? null ;
367380 }
368381 }
369382
370- if ( hasIndexCubed && hasBinomial && binomialN && upper . isSame ( binomialN ) && body . ops . length === 2 ) {
383+ if (
384+ hasIndexCubed &&
385+ hasBinomial &&
386+ binomialN &&
387+ upper . isSame ( binomialN ) &&
388+ body . ops . length === 2
389+ ) {
371390 // n²(n+3) * 2^(n-3)
372391 const n = binomialN ;
373392 const result = ce . function ( 'Multiply' , [
@@ -385,7 +404,11 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
385404 hasBinomial = false ;
386405
387406 for ( const op of body . ops ) {
388- if ( op . operator === 'Power' && op . op1 ?. is ( - 1 ) && op . op2 ?. symbol === index ) {
407+ if (
408+ op . operator === 'Power' &&
409+ op . op1 ?. is ( - 1 ) &&
410+ op . op2 ?. symbol === index
411+ ) {
389412 hasAltTerm = true ;
390413 } else if ( op . symbol === index ) {
391414 hasIndexTerm = true ;
@@ -395,7 +418,14 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
395418 }
396419 }
397420
398- if ( hasAltTerm && hasIndexTerm && hasBinomial && binomialN && upper . isSame ( binomialN ) && body . ops . length === 3 ) {
421+ if (
422+ hasAltTerm &&
423+ hasIndexTerm &&
424+ hasBinomial &&
425+ binomialN &&
426+ upper . isSame ( binomialN ) &&
427+ body . ops . length === 3
428+ ) {
399429 // For n >= 2, sum = 0
400430 return { value : ce . Zero , because : 'alternating weighted binomial sum' } ;
401431 }
@@ -422,11 +452,7 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
422452 }
423453
424454 // Sum of k*(k+1): Sum(k*(k+1), [k, 1, n]) → n(n+1)(n+2)/3
425- if (
426- body . operator === 'Multiply' &&
427- body . ops ?. length === 2 &&
428- lower . is ( 1 )
429- ) {
455+ if ( body . operator === 'Multiply' && body . ops ?. length === 2 && lower . is ( 1 ) ) {
430456 const [ op1 , op2 ] = body . ops ;
431457 // Check for k * (k+1) pattern
432458 const isKTimesKPlus1 =
@@ -506,7 +532,10 @@ export function simplifySum(x: BoxedExpression): RuleStep | undefined {
506532 // (n - 1) / n
507533 const n = upper ;
508534 const result = n . sub ( ce . One ) . div ( n ) ;
509- return { value : result , because : 'partial fractions (telescoping k*(k-1))' } ;
535+ return {
536+ value : result ,
537+ because : 'partial fractions (telescoping k*(k-1))' ,
538+ } ;
510539 }
511540 }
512541 }
0 commit comments