/// <summary> /// generic dswap /// </summary> static public void dswap <U, V>(int N, U DX, int INCX, V DY, int INCY) where U : IList <double> where V : IList <double> { if (object.ReferenceEquals(DX, DY)) { // while formally there is no problem that this should work, it seems much more likely // that it's a bug. throw new ArgumentException("Illegal use: reference-equality of input vectors -- this might be a mis-use instead of intention."); } if ((DX is double[]) && (DY is double[])) { BLAS.dswap(N, DX as double[], INCX, DY as double[], INCY); return; } else { for (int i = 0; i < N; i++) { double a; a = DX[i * INCX]; DX[i * INCX] = DY[i * INCY]; DY[i * INCY] = a; } } }
/// <summary> /// MPI-parallel 2-norm /// </summary> static public double drnm2 <TX>(int N, TX x, int incx, MPI_Comm comm) where TX : IList <double> { double locRes = 0; double[] dx = x as double[]; if (dx != null) { // double[] - implementation locRes = BLAS.dnrm2(N, dx, incx); locRes = locRes * locRes; } else { ISparseVector <double> spx = x as ISparseVector <double>; if (spx != null) { // sparse implementation foreach (var entry in spx.SparseStruct) { int m = entry.Key % incx; if (m != 0) { // entry is skipped by x-increment continue; } double xi = entry.Value; locRes += xi * xi; } } else { // default implementation for (int n = 0; n < N; n++) { double xi = x[n * incx]; locRes += xi * xi; } } } double globRes = double.NaN; unsafe { csMPI.Raw.Allreduce((IntPtr)(&locRes), (IntPtr)(&globRes), 1, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.SUM, comm); } return(Math.Sqrt(globRes)); }
/// <summary> /// blas dscal: <paramref name="X"/> = <paramref name="X"/>*<paramref name="alpha"/>; /// </summary> static public void dscal <T>(int N, double alpha, T X, int incx) where T : IList <double> { ISparseVector <double> spx = X as ISparseVector <double>; double[] arx = X as double[]; if (arx != null) { // double - array -> use BLAS // ++++++++++++++++++++++++++ BLAS.dscal(N, alpha, arx, incx); return; } if (spx != null) { // sparce vector -> compute only nonzero entries // +++++++++++++++++++++++++++++++++++++++++++++ int[] idx = new int[spx.NonZeros]; spx.SparseStruct.Keys.CopyTo(idx, 0); foreach (int i in idx) { int m = i % incx; if (m != 0) { // entry is skipped by x-increment continue; } spx[i] *= alpha; } return; } { // reference version // +++++++++++++++++ for (int i = 0; i < N; i += incx) { X[i] *= alpha; } } }
/// <summary> /// MPI - parallel scalar product /// </summary> static public double ddot <TX, TY>(int N, TX x, int incx, TY y, int incy, MPI.Wrappers.MPI_Comm comm) where TX : IList <double> where TY : IList <double> { if (incx * x.Count < N) { throw new ArgumentException("vector too short.", "x"); } if (incy * y.Count < N) { throw new ArgumentException("vector too short.", "y"); } double locRes = 0; double[] dx = x as double[]; double[] dy = y as double[]; if (dx != null && dy != null) { // use dnese BLAS locRes = BLAS.ddot(N, dx, incx, dy, incy); } else { ISparseVector <double> spx = x as ISparseVector <double>; ISparseVector <double> spy = y as ISparseVector <double>; IList <double> _y = y; if (spy != null) { if (spx == null || spy.Sparsity < spx.Sparsity) { // y is sparser than x, use y ! spx = spy; spy = null; _y = x; x = default(TX); y = default(TY); int buffy = incx; incx = incy; incy = buffy; } } if (spx != null) { // sparse implementation foreach (var entry in spx.SparseStruct) { int m = entry.Key % incx; if (m != 0) { // entry is skipped by x-increment continue; } int n = entry.Key / incx; locRes += entry.Value * _y[n * incy]; } } else { // default IList<double> - implementation for (int n = 0; n < N; n++) { locRes += x[n * incx] * y[n * incy]; } } } double globRes = double.NaN; unsafe { csMPI.Raw.Allreduce((IntPtr)(&locRes), (IntPtr)(&globRes), 1, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.SUM, comm); } return(globRes); }
/// <summary> /// blas daxpy: <paramref name="Y"/> = <paramref name="Y"/> + <paramref name="alpha"/>*<paramref name="X"/>; /// </summary> static public void daxpy <TX, TY>(int N, double alpha, TX X, int INCX, TY Y, int INCY) where TX : IList <double> where TY : IList <double> { if (object.ReferenceEquals(X, Y)) { // while formally there is no problem that this should work, it seems much more likely // that it's a bug. throw new ArgumentException("Illegal use: reference-equality of input vectors -- this might be a mis-use instead of intention."); } { // sparse vector branch // ++++++++++++++++++++ ISparseVector <double> spx = X as ISparseVector <double>; if (spx != null) { foreach (var entry in spx.SparseStruct) { int m = entry.Key % INCX; if (m != 0) { // entry is skipped by x-increment continue; } int n = entry.Key / INCX; double xi = entry.Value; Y[n * INCY] += xi * alpha; } return; } } { // both arrays-branch -> use BLAS // ++++++++++++++++++++++++++++++ double[] _XasDouble = X as double[]; double[] _YasDouble = Y as double[]; if (_XasDouble != null && _YasDouble != null) { BLAS.daxpy(N, alpha, _XasDouble, INCX, _YasDouble, INCY); return; } } { // default branch // ++++++++++++++ for (int n = 0; n < N; n++) { Y[n * INCY] += X[n * INCX] * alpha; } return; } }