license import { backend_util , DataType , TypedArray , util } from '@tensorflow/tfjs-core' ; export function sparseFillEmptyRowsImpl ( indices , indicesShape , indicesDType , values , valuesDType , denseShape , defaultValue ) { const indicesCount = indicesShape [ 0 ] ; const denseRows = denseShape [ 0 ] ; const emptyRowIndicator = new Array ( denseRows ) ; const reverseIndexMap = new Array ( indicesCount ) ; const rank = indicesShape [ 1 ] ; if ( denseRows === 0 ) { if ( indicesCount !== 0 ) { throw new Error ( backend_util . getSparseFillEmptyRowsIndicesDenseShapeMismatch ( indicesCount ) ) ; } const outputIndices = util . getArrayFromDType ( indicesDType , 0 ) as TypedArray ; const outputValues = util . getArrayFromDType ( valuesDType , 0 ) as TypedArray ; return [ outputIndices , [ 0 , rank ] , outputValues , emptyRowIndicator , reverseIndexMap ] ; } let rowsAreOrdered = true ; let lastIndicesRow = 0 ; const csrOffset = new Array ( denseRows ) . fill ( 0 ) ; for ( let i = 0 ; i < indicesCount ; ++ i ) { const row = indices [ i * rank ] ; if ( row < 0 ) { throw new Error ( backend_util . getSparseFillEmptyRowsNegativeIndexErrorMessage ( i , row ) ) ; } if ( row >= denseRows ) { throw new Error ( backend_util . getSparseFillEmptyRowsOutOfRangeIndexErrorMessage ( i , row , denseRows ) ) ; } ++ csrOffset [ row ] ; rowsAreOrdered = rowsAreOrdered && ( row >= lastIndicesRow ) ; lastIndicesRow = row ; } let allRowsFull = true ; for ( let row = 0 ; row < denseRows ; ++ row ) { const rowEmpty = ( csrOffset [ row ] === 0 ) ; emptyRowIndicator [ row ] = rowEmpty ; allRowsFull = allRowsFull && ! rowEmpty ; csrOffset [ row ] = Math . max ( csrOffset [ row ] , 1 ) ; if ( row > 0 ) { csrOffset [ row ] += csrOffset [ row - 1 ] ; } } if ( allRowsFull && rowsAreOrdered ) { const outputIndices = indices ; const outputValues = values ; for ( let i = 0 ; i < indicesCount ; ++ i ) { reverseIndexMap [ i ] = i ; } return [ outputIndices , [ indicesCount , rank ] , outputValues , emptyRowIndicator , reverseIndexMap ] ; } else { const fullIndicesCount = csrOffset [ denseRows - 1 ] ; const outputIndices = util . getArrayFromDType ( indicesDType , fullIndicesCount * rank ) as TypedArray ; const outputValues = util . getArrayFromDType ( valuesDType , fullIndicesCount ) as TypedArray ; const filledCount = new Array ( denseRows ) . fill ( 0 ) ; for ( let i = 0 ; i < indicesCount ; ++ i ) { const row = indices [ i * rank ] ; const offset = filledCount [ row ] ; const outputI = ( ( row === 0 ) ? 0 : csrOffset [ row - 1 ] ) + offset ; filledCount [ row ] ++ ; for ( let j = 0 ; j < rank ; ++ j ) { outputIndices [ outputI * rank + j ] = indices [ i * rank + j ] ; } outputValues [ outputI ] = values [ i ] ; reverseIndexMap [ i ] = outputI ; } for ( let row = 0 ; row < denseRows ; ++ row ) { const rowCount = filledCount [ row ] ; if ( rowCount === 0 ) { const startingIndex = ( row === 0 ) ? 0 : csrOffset [ row - 1 ] ; outputIndices [ startingIndex * rank + 0 ] = row ; for ( let col = 1 ; col < rank ; ++ col ) { outputIndices [ startingIndex * rank + col ] = 0 ; } outputValues [ startingIndex ] = defaultValue ; } } return [ outputIndices , [ fullIndicesCount , rank ] , outputValues , emptyRowIndicator , reverseIndexMap ] ; } }