license /**
 * This differs from util.assertShapesMatch in that it allows values of
 * negative one, an undefined size of a dimensinon, in a shape to match
 * anything.
 */ import { Tensor , util } from '@tensorflow/tfjs-core' ; param shapeA param shapeB param errorMessagePrefix export function assertShapesMatchAllowUndefinedSize ( shapeA , shapeB , errorMessagePrefix = '' ) { if ( typeof shapeA === 'number' || typeof shapeB === 'number' ) { return ; } util . assert ( shapeA . length === shapeB . length , ( ) => errorMessagePrefix + ` Shapes ${ shapeA } and ${ shapeB } must match` ) ; for ( let i = 0 ; i < shapeA . length ; i ++ ) { const dim0 = shapeA [ i ] ; const dim1 = shapeB [ i ] ; util . assert ( dim0 < 0 || dim1 < 0 || dim0 === dim1 , ( ) => errorMessagePrefix + ` Shapes ${ shapeA } and ${ shapeB } must match` ) ; } } export function fullDefinedShape ( elementShape ) { if ( typeof elementShape === 'number' || elementShape . some ( dim => dim < 0 ) ) { return false ; } return true ; } param listElementShape param tensors param elementShape export function inferElementShape ( listElementShape , tensors , elementShape ) { let partialShape = mergeElementShape ( listElementShape , elementShape ) ; const notfullDefinedShape = ! fullDefinedShape ( partialShape ) ; if ( notfullDefinedShape && tensors . length === 0 ) { throw new Error ( `Tried to calculate elements of an empty list` + ` with non-fully-defined elementShape: ${ partialShape }` ) ; } if ( notfullDefinedShape ) { tensors . forEach ( tensor => { partialShape = mergeElementShape ( tensor . shape , partialShape ) ; } ) ; } if ( ! fullDefinedShape ( partialShape ) ) { throw new Error ( `Non-fully-defined elementShape: ${ partialShape }` ) ; } return partialShape as number [ ] ; } export function mergeElementShape ( elementShapeA , elementShapeB ) { if ( typeof elementShapeA === 'number' ) { return elementShapeB ; } if ( typeof elementShapeB === 'number' ) { return elementShapeA ; } if ( elementShapeA . length !== elementShapeB . length ) { throw new Error ( `Incompatible ranks during merge: ${ elementShapeA } vs. ${ elementShapeB }` ) ; } const result = [ ] ; for ( let i = 0 ; i < elementShapeA . length ; ++ i ) { const dim0 = elementShapeA [ i ] ; const dim1 = elementShapeB [ i ] ; if ( dim0 >= 0 && dim1 >= 0 && dim0 !== dim1 ) { throw new Error ( `Incompatible shape during merge: ${ elementShapeA } vs. ${ elementShapeB }` ) ; } result [ i ] = dim0 >= 0 ? dim0 : dim1 ; } return result ; }