public IVector Mul(IVector v, IComputationEnvironment env, bool ForceDenseFormat = false) { var ev = v as EncryptedSealBfvVector; var lenv = env as EncryptedSealBfvEnvironment; if (Format == EMatrixFormat.ColumnMajor) { if (ForceDenseFormat) { throw new Exception("Forcing dense format is available only in RowMajor mode"); } return(EncryptedSealBfvVector.DenseMatrixBySparseVectorMultiply(leVectors, ev, lenv)); } if (!ForceDenseFormat) { IVector[] tempVectors = new EncryptedSealBfvVector[leVectors.Length]; Utils.ParallelProcessInEnv(leVectors.Length, env, (penv, task, colIndex) => { tempVectors[colIndex] = leVectors[colIndex].DotProduct(ev, penv); }); var res = EncryptedSealBfvVector.GenerateSpareOfArray(tempVectors, env); foreach (var t in tempVectors) { t.Dispose(); } return(res); } // Column major mode forcing dense output; { var sumVectors = new EncryptedSealBfvVector[Defaults.ThreadCount]; Utils.ParallelProcessInEnv(leVectors.Length, env, (penv, task, colIndex) => { var t = (EncryptedSealBfvVector)leVectors[colIndex].DotProduct(ev, penv, ForceOutputInColumn: colIndex); var s = sumVectors[task]; sumVectors[task] = (sumVectors[task] == null) ? t : (EncryptedSealBfvVector)sumVectors[task].Add(t, env); if (sumVectors[task] != t) { t.Dispose(); } if (s != null) { s.Dispose(); } }); EncryptedSealBfvVector sum = null; for (int i = 0; i < sumVectors.Length; i++) { if (sumVectors[i] == null) { continue; } if (sum == null) { sum = sumVectors[i]; } else { var t = sum; sum = (EncryptedSealBfvVector)sum.Add(sumVectors[i], env); t.Dispose(); sumVectors[i].Dispose(); } } sum.RegisterDim((ulong)leVectors.Length); if (sum.Format != EVectorFormat.dense) { throw new Exception("Internal probloem: expecting the output to be dense"); } return(sum); } }