@SuppressWarnings("unchecked")
    public static <T extends Number> SparseMatrix mulSparseMatrixWithSparseMatrix(SparseMatrix a, SparseMatrix b, Class<T> type) {
	SparseMatrix result = null;
	try {
	    if (a == null || b == null) {
		throw new NullPointerException();
	    }
	    
	    int size = a.getSize();
	    
	    result = MatrixBuildUtils.buildEmptySparseMatrix(size);
	    
	    ArrayList<ArrayList<Integer>> aRowIndexes = getClone(a.getRowIndexes(), Integer.class);
	    
	    for (int row = 0; row < size; row++) {
		ArrayList<Integer> rowInRowIndexes = aRowIndexes.get(row);
		
		for (int colOfElemInB = 0; colOfElemInB < size; colOfElemInB++) {
		    T elem = ElementOpUtils.getNeutralSumElem(type);
		    T elOfA = (T) a.getElement(row, row);
		    T elOfB = (T) b.getElement(row, colOfElemInB);
		    elem = ElementOpUtils.sum(elem, ElementOpUtils.mul(elOfA, elOfB, type), type);
		    
		    for (Integer col : rowInRowIndexes) {
			elOfA = (T) a.getElement(row, col);
			elOfB = (T) b.getElement(col, colOfElemInB);
			if (((Double) elOfB).doubleValue() != 0.0) {
			    elem = ElementOpUtils.sum(elem, ElementOpUtils.mul(elOfA, elOfB, type), type);
			}
		    }
		    result.setElement(row, colOfElemInB, (Double) elem);
		    elem = ElementOpUtils.getNeutralSumElem(type);
		}
	    }
	    return result;
	} catch (NullPointerException e) {
	    Logger.getGlobal().log(Level.SEVERE, "cannot multiply null matrixes");
	    e.printStackTrace();
	    return null;
	} catch (IndexOutOfBoundsException e) {
	    Logger.getGlobal().log(Level.SEVERE, "check your indexes when multiplying matrixes");
	    e.printStackTrace();
	    return null;
	}
    }