docs: public static void multTransA(DMatrixSparseCSC A, DMatrixSparseCSC B, DMatrixSparseCSC C,
                                    @Nullable IGrowArray gw, @Nullable DGrowArray gx )
      {
          double []x = adjust(gx, A.numRows);
          int []w = adjust(gw, A.numRows, A.numRows);
  
          C.growMaxLength(A.nz_length+B.nz_length,false);
          C.indicesSorted = true;
          C.nz_length = 0;
          C.col_idx[0] = 0;
  
          int idxB0 = B.col_idx[0];
          for (int bj = 1; bj <= B.numCols; bj++) {
              int idxB1 = B.col_idx[bj];
              C.col_idx[bj] = C.nz_length;
  
              if (idxB0 == idxB1) {
                  continue;
              }
  
              // convert the column of B into a dense format and mark which rows are used
              for (int bi = idxB0; bi < idxB1; bi++) {
                  int rowB = B.nz_rows[bi];
                  x[rowB] = B.nz_values[bi];
                  w[rowB] = bj;
              }
  
              // C(colA,colB) = A(:,colA)*B(:,colB)
              for (int colA = 0; colA < A.numCols; colA++) {
                  int idxA0 = A.col_idx[colA];
                  int idxA1 = A.col_idx[colA + 1];
  
                  double sum = 0;
                  for (int ai = idxA0; ai < idxA1; ai++) {
                      int rowA = A.nz_rows[ai];
                      if (w[rowA] == bj) {
                          sum += x[rowA] * A.nz_values[ai];
                      }
                  }
  
                  if (sum != 0) {
                      if( C.nz_length == C.nz_values.length ) {
                          C.growMaxLength(C.nz_length*2+1,true);
                      }
                      C.nz_values[C.nz_length] = sum;
                      C.nz_rows[C.nz_length++] = colA;
                  }
              }
              C.col_idx[bj] = C.nz_length;
              idxB0 = idxB1;
          }
      }