@@ -534,7 +534,14 @@ export class StaticTapeBuilder {
534534 // Reverse topological traversal
535535 for ( let i = this . ops . length - 1 ; i >= 0 ; i -- ) {
536536 const op = this . ops [ i ] ! ; // eslint-disable-line @typescript-eslint/no-non-null-assertion
537- if ( op . type === "const" || op . type === "var" ) continue ;
537+ if (
538+ op . type === "const" ||
539+ op . type === "var" ||
540+ op . type === "vec_var" ||
541+ op . type === "vec_const" ||
542+ op . type === "nop"
543+ )
544+ continue ;
538545
539546 // Optimization: if dt is 0, skip branching
540547 lines . push ( ` if (dt[${ i } ] != 0.0) {` ) ;
@@ -580,6 +587,29 @@ export class StaticTapeBuilder {
580587 case "sqrt" :
581588 lines . push ( ` dt[${ op . a } ] += dt[${ i } ] / (2.0 * t[${ i } ]);` ) ;
582589 break ;
590+ // ── Vector ops ──
591+ case "vec_add" :
592+ lines . push ( ` for (int _k = 0; _k < ${ op . size } ; _k++) {` ) ;
593+ lines . push ( ` dt[${ op . a } +_k] += dt[${ i } +_k]; dt[${ op . b } +_k] += dt[${ i } +_k];` ) ;
594+ lines . push ( ` }` ) ;
595+ break ;
596+ case "vec_sub" :
597+ lines . push ( ` for (int _k = 0; _k < ${ op . size } ; _k++) {` ) ;
598+ lines . push ( ` dt[${ op . a } +_k] += dt[${ i } +_k]; dt[${ op . b } +_k] -= dt[${ i } +_k];` ) ;
599+ lines . push ( ` }` ) ;
600+ break ;
601+ case "vec_mul" :
602+ lines . push ( ` for (int _k = 0; _k < ${ op . size } ; _k++) {` ) ;
603+ lines . push ( ` dt[${ op . a } +_k] += dt[${ i } +_k] * t[${ op . b } +_k];` ) ;
604+ lines . push ( ` dt[${ op . b } +_k] += dt[${ i } +_k] * t[${ op . a } +_k];` ) ;
605+ lines . push ( ` }` ) ;
606+ break ;
607+ case "vec_neg" :
608+ lines . push ( ` for (int _k = 0; _k < ${ op . size } ; _k++) dt[${ op . a } +_k] -= dt[${ i } +_k];` ) ;
609+ break ;
610+ case "vec_subscript" :
611+ lines . push ( ` dt[${ op . a + op . offset } ] += dt[${ i } ];` ) ;
612+ break ;
583613 }
584614 lines . push ( ` }` ) ;
585615 }
@@ -592,6 +622,10 @@ export class StaticTapeBuilder {
592622 // Variables can be read multiple times (e.g. x in x + x).
593623 // Since `cache` deduplicates, there is only one `var: x` operator!
594624 gradients . set ( op . name , i ) ;
625+ } else if ( op . type === "vec_var" ) {
626+ for ( let k = 0 ; k < op . size ; k ++ ) {
627+ gradients . set ( `${ op . baseName } [${ k + 1 } ]` , i + k ) ;
628+ }
595629 }
596630 }
597631
0 commit comments