public static void matrixMultWDivMM(MatrixBlock mW,MatrixBlock mU,MatrixBlock mV,MatrixBlock mX,MatrixBlock ret,WDivMMType wt,int k) throws DMLRuntimeException {
  if (mW.isEmptyBlock(false) || (wt.isLeft() && mU.isEmptyBlock(false)) || (wt.isRight() && mV.isEmptyBlock(false))|| (wt.isBasic() && mW.isEmptyBlock(false))) {
    ret.examSparsity();
    return;
  }
  ret.sparse=wt.isBasic() ? mW.sparse : false;
  ret.allocateDenseOrSparseBlock();
  if (!ret.isThreadSafe()) {
    matrixMultWDivMM(mW,mU,mV,mX,ret,wt);
    return;
  }
  try {
    ExecutorService pool=Executors.newFixedThreadPool(k);
    ArrayList<MatrixMultWDivTask> tasks=new ArrayList<MatrixMultWDivTask>();
    if (wt.isLeft()) {
      int blklen=(int)(Math.ceil((double)mW.clen / k));
      for (int j=0; j < k & j * blklen < mW.clen; j++)       tasks.add(new MatrixMultWDivTask(mW,mU,mV,mX,ret,wt,0,mW.rlen,j * blklen,Math.min((j + 1) * blklen,mW.clen)));
    }
 else {
      int blklen=(int)(Math.ceil((double)mW.rlen / k));
      for (int i=0; i < k & i * blklen < mW.rlen; i++)       tasks.add(new MatrixMultWDivTask(mW,mU,mV,mX,ret,wt,i * blklen,Math.min((i + 1) * blklen,mW.rlen),0,mW.clen));
    }
    List<Future<Long>> taskret=pool.invokeAll(tasks);
    pool.shutdown();
    ret.nonZeros=0;
    for (    Future<Long> task : taskret)     ret.nonZeros+=task.get();
  }
 catch (  Exception e) {
    throw new DMLRuntimeException(e);
  }
  ret.examSparsity();
}

public static void matrixMultWDivMM ( MatrixBlock mW , MatrixBlock mU , MatrixBlock mV , MatrixBlock mX , MatrixBlock ret , WDivMMType wt , int k ) throws DMLRuntimeException { if ( mW . isEmptyBlock ( false ) || ( wt . isLeft ( ) && mU . isEmptyBlock ( false ) ) || ( wt . isRight ( ) && mV . isEmptyBlock ( false ) ) || ( wt . isBasic ( ) && mW . isEmptyBlock ( false ) ) ) { ret . examSparsity ( ) ; return ; } ret . sparse = wt . isBasic ( ) ? mW . sparse : false ; ret . allocateDenseOrSparseBlock ( ) ; if ( ! ret . isThreadSafe ( ) ) { matrixMultWDivMM ( mW , mU , mV , mX , ret , wt ) ; return ; } try { ExecutorService pool = Executors . newFixedThreadPool ( k ) ; ArrayList < MatrixMultWDivTask > tasks = new ArrayList < MatrixMultWDivTask > ( ) ; if ( wt . isLeft ( ) ) { int blklen = ( int ) ( Math . ceil ( ( double ) mW . clen / k ) ) ; for ( int j = 0 ; j < k & j * blklen < mW . clen ; j ++ ) tasks . add ( new MatrixMultWDivTask ( mW , mU , mV , mX , ret , wt , 0 , mW . rlen , j * blklen , Math . min ( ( j + 1 ) * blklen , mW . clen ) ) ) ; } else { int blklen = ( int ) ( Math . ceil ( ( double ) mW . rlen / k ) ) ; for ( int i = 0 ; i < k & i * blklen < mW . rlen ; i ++ ) tasks . add ( new MatrixMultWDivTask ( mW , mU , mV , mX , ret , wt , i * blklen , Math . min ( ( i + 1 ) * blklen , mW . rlen ) , 0 , mW . clen ) ) ; } List < Future < Long > > taskret = pool . invokeAll ( tasks ) ; pool . shutdown ( ) ; ret . nonZeros = 0 ; for ( Future < Long > task : taskret ) ret . nonZeros += task . get ( ) ; } catch ( Exception e ) { throw new DMLRuntimeException ( e ) ; } ret . examSparsity ( ) ; }
note : this operation has limited nan support , which is acceptable because all our sparse - safe operations have only limited nan support . if this is not intended behavior , please disable the rewrite . in detail , this operator will produce for w / ( u % * % t ( v ) ) a zero intermediate for each zero in w ( even if uvij is zero which would give 0 / 0 = nan ) but inf / - inf for non - zero entries in v where the corresponding cell in ( y % * % x ) is zero .
