import { CommandInterface } from '../Commands' ; import * as Constants from '../Constants' ; import { Variables } from './Variables' ; import { Variable } from './Variable' ; import { Matrix } from './Matrix' ; export class SparseMatrix extends Matrix { private static readonly TYPENAME_PREFIX : string = 'sparse' ; private static readonly TYPENAME_SUFFIX : string = 'matrix' ; private static readonly TYPENAME : string = `${ SparseMatrix . TYPENAME_PREFIX } ${ SparseMatrix . TYPENAME_SUFFIX }` ; private static readonly TYPENAME_REGEX = new RegExp ( `${ SparseMatrix . TYPENAME_PREFIX } (?:\\w+ )?${ SparseMatrix . TYPENAME_SUFFIX }` ) ; private _indices : Array < number > ; param name param value param freeIndices param fixedIndices param validValue constructor ( name = '' , value = '' , freeIndices = [ ] , fixedIndices = [ ] , validValue = true , type = SparseMatrix . TYPENAME ) { super ( name , value , freeIndices , fixedIndices , validValue , type ) ; this . _indices = new Array < number > ( this . _numberOfChildren ) ; } public indices ( ) { return this . _indices ; } public loads ( type ) { return type . match ( SparseMatrix . TYPENAME_REGEX ) !== null ; } public createConcreteType ( name , value , freeIndices , fixedIndices , validValue , type ) { return new SparseMatrix ( name , value , freeIndices , fixedIndices , validValue , type ) ; } public loadNew ( name , type , runtime , callback ) { Variables . getNonZero ( name , runtime , ( n ) => { const size = [ n ] ; const loadable = Variables . loadable ( size ) ; const buildWith = ( value ) => { const matrix = this . createConcreteType ( name , value , size , [ ] , loadable , type ) ; if ( loadable ) { matrix . fetchIndices ( runtime , 0 , 0 , ( ) => { callback ( matrix ) ; } ) ; } else { callback ( matrix ) ; } } ; if ( loadable ) { Variables . getValue ( name , runtime , buildWith ) ; } else { buildWith ( size . join ( Constants . SIZE_SEPARATOR ) ) ; } } ) ; } public fetchChildren ( runtime , offset , count , callback ) { this . fetchIndices ( runtime , offset , count , ( fetchedIndices ) => { const begin = 1 + offset ; const end = begin + count - 1 ; const exp = `${ this . name ( ) }(find(${ this . name ( ) })(${ begin }:${ end }))` ; runtime . evaluateAsLine ( exp , ( value ) => { this . parseChildren ( value , offset , count , ( children ) => { callback ( children ) ; } ) ; } ) ; } ) ; } public fetchIndices ( runtime , offset , count , callback ) { if ( count === 0 && count === 0 ) { count = this . _numberOfChildren ; } const begin = 1 + offset ; const end = begin + count - 1 ; const idxExp = `find(${ this . name ( ) })(${ begin }:${ end })` ; runtime . evaluateAsLine ( idxExp , ( output ) => { output = Variables . clean ( output ) ; const values = output . split ( '\n' ) ; const indices = values . map ( i => parseInt ( i ) ) ; for ( let i = 0 ; i !== indices . length ; ++ i ) { this . _indices [ offset + i ] = indices [ i ] ; } callback ( indices ) ; } ) ; } public parseChildren ( value , offset , count , callback ) { const childFreeIndices = [ ] ; const vars = new Array < Variable > ( count ) ; const values = SparseMatrix . extractValues ( value ) ; if ( values . length !== count ) { throw `values.length: ${ values . length } != ${ count }!` ; } for ( let i = 0 ; i !== count ; ++ i ) { const childFixedIndices = [ this . _indices [ i + offset ] ] ; const name = this . basename ( ) ; const val = '' + values [ i ] ; vars [ i ] = this . createConcreteType ( name , val , childFreeIndices , childFixedIndices , true , this . typename ( ) ) ; } callback ( vars ) ; } private static readonly VALUES_REGEX = /^\s*\(\d+,\s+\d+\)\s+->\s+(.+)$/ ; public static extractValues ( value ) { const lines = value . split ( '\n' ) ; const values = new Array < string > ( ) ; lines . forEach ( line => { const match = line . match ( SparseMatrix . VALUES_REGEX ) ; if ( match !== null && match . length === 2 ) { const value = match [ 1 ] ; values . push ( value ) ; } } ) ; return values ; } }