Forward Substitution (Column-major)

// import visualization libraries {
const { Array2DTracer, Layout, LogTracer, Tracer, VerticalLayout, HorizonLayout } = require( 'algorithm-visualizer' );
// }

// define tracer variables {
const matrixTracer = new Array2DTracer( 'L x = b (column-major)' );
const logTracer = new LogTracer( 'Console' );
Layout.setRoot( new VerticalLayout( [ matrixTracer, logTracer ] ) );
// }

const random_range = 3;
const N = 8;
// initialization {
const matrix = [];
for ( let i = 0; i < N; ++i )
{
    matrix.push( [] );
    for ( let j = 0; j <= i; ++j ) matrix[ i ].push( Math.random() * ( 2 * random_range ) - random_range );
    for ( let j = i + 1; j < N; ++j ) matrix[ i ].push( 0 );
    while ( Math.abs( matrix[ i ][ i ] ) < 1e-6 ) matrix[ i ][ i ] = Math.random() * ( 2 * random_range ) - random_range;
    matrix[ i ].push( 'x[' + i + ']:' );
    matrix[ i ].push( 'x' + i );
    matrix[ i ].push( 'b[' + i + ']:' );
    matrix[ i ].push( Math.random() * ( 2 * random_range ) - random_range );
}
// }

// visualization {
matrixTracer.set( matrix );
Tracer.delay();
// }

// visualization {
logTracer.println( 'Copying from b' );
// }
for ( let i = 0; i < N; ++i )
{
    matrix[ i ][ N + 1 ] = matrix[ i ][ N + 3 ];
    // visualization {
    matrixTracer.select( i, N + 3 );
    matrixTracer.patch( i, N + 1, matrix[ i ][ N + 1 ] );
    logTracer.println( 'x[' + i + '] = b[' + i + ']' );
    Tracer.delay();
    matrixTracer.deselect( i, N + 3 );
    matrixTracer.depatch( i, N + 1 );
    // }
}

for ( let i = 0; i < N; ++i )
{
    matrix[ i ][ N + 1 ] /= matrix[ i ][ i ];
    // visualization {
    logTracer.println( 'Dealing with Column ' + i );
    matrixTracer.select( i, i );
    matrixTracer.patch( i, N + 1, matrix[ i ][ N + 1 ] );
    logTracer.println( 'x[' + i + '] = x[' + i + '] / L[' + i + '][' + i + ']' );
    logTracer.println( 'x[' + i + '] = ' + matrix[ i ][ N + 1 ] );
    Tracer.delay();
    matrixTracer.deselect( i, i );
    matrixTracer.depatch( i, N + 1 );
    // }
    for ( let j = i + 1; j < N; ++j )
    {
        matrix[ j ][ N + 1 ] -= matrix[ j ][ i ] * matrix[ i ][ N + 1 ];
        // visualization {
        logTracer.println( 'x[' + j + '] = x[' + j + '] - L[' + j + '][' + i + '] x[' + i + ']' );
        matrixTracer.select( j, i );
        matrixTracer.select( i, N + 1 );
        matrixTracer.patch( j, N + 1, matrix[ j ][ N + 1 ] );
        Tracer.delay();
        matrixTracer.deselect( j, i );
        matrixTracer.deselect( i, N + 1 );
        matrixTracer.depatch( j, N + 1 );
        // }
    }
}