/// <summary> /// See <see cref="IMatrixView.Axpy(IMatrixView, double)"/>. /// </summary> public IMatrix Axpy(IMatrixView otherMatrix, double otherCoefficient) { if (otherMatrix is CsrMatrix otherCSR) // In case both matrices have the exact same index arrays { if (HasSameIndexer(otherCSR)) { // Do not copy the index arrays, since they are already spread around. TODO: is this a good idea? double[] resultValues = new double[values.Length]; Array.Copy(this.values, resultValues, values.Length); Blas.Daxpy(values.Length, otherCoefficient, otherCSR.values, 0, 1, resultValues, 0, 1); return(new CsrMatrix(NumRows, NumColumns, resultValues, this.colIndices, this.rowOffsets)); } } // All entries must be processed. TODO: optimizations may be possible (e.g. only access the nnz in this matrix) return(DenseStrategies.LinearCombination(this, 1.0, otherMatrix, otherCoefficient)); }
/// <summary> /// The basic Combine version /// result = alpha * (T . x) . y + beta * result /// </summary> public static Array <Real> Combine21(this Array <Real> t, Array <Real> x, Array <Real> y, Array <Real> result = null, Real alpha = 1, Real beta = 0) { if (t.Shape[2] != x.Shape[0] && t.Shape[1] != y.Shape[0]) { throw new ArgumentException(); } if (t.Stride[2] != 1) { throw new NotImplementedException(); } int offsetT = t.Offset; if (result == null) { result = new Array <Real>(t.Shape[0]); } else { result.Scale(beta, result: result); } int offsetRes = result.Offset; int strideRes = result.Stride[0]; int offsetX = x.Offset; int strideX = x.Stride[0]; int strideJ = y.Stride[0]; int J = y.Shape[0] * strideJ + y.Offset; for (int j = y.Offset; j < J; j += strideJ) { // result += alpha * y[j] * (t[:, j, :] . x) Blas.gemv(Order.RowMajor, Transpose.NoTrans, t.Shape[0], t.Shape[2], alpha * y.Values[j], t.Values, offsetT, t.Stride[0], x.Values, offsetX, strideX, 1, result.Values, offsetRes, strideRes ); offsetT += t.Stride[1]; } return(result); }
private void vocToWav(Stream s) { BinaryWriter bw = new BinaryWriter(s); Blas blas = _currentBlas; // WAV_HEADER bw.Write("RIFF".ToCharArray()); s.Position += 4; // skip over, come back to later, P = 4 (file.length-8) bw.Write("WAVE".ToCharArray()); // WAV_DATA_BLOCK // fmt_HEADER bw.Write("fmt ".ToCharArray()); bw.Write((uint)16); // fmt block length // fmt_DATA_BLOCK bw.Write((short)1); // uncompressed PCM bw.Write((short)1); // NumChannels (Mono) bw.Write((uint)blas.Frequency); // SampleRate bw.Write((uint)blas.Frequency); // ByteRate (SampleRate * NumChannels * BitsPerSample/8) [SR * 1 * 8/8] bw.Write((short)1); // BlockAlign (NumChannels * BitsPerSample/8) [1 * 8/8] bw.Write((short)8); // BitsPerSample // data_HEADER bw.Write("data".ToCharArray()); s.Position += 4; // skip over, come back to later, P = 40 (file.length-44); foreach (Blas.SoundDataBlock sdb in blas.SoundBlocks) { if (sdb.Data != null) { if (sdb.DoesRepeat) { for (int i = 0; i < (sdb.NumberOfRepeats != -1 ? sdb.NumberOfRepeats + 1 : 4); i++) // repeat 4 times for infinite repeats { bw.Write(sdb.Data); } } else { bw.Write(sdb.Data); } } } s.SetLength(s.Position); s.Position = 4; bw.Write((uint)(s.Length - 8)); s.Position = 40; bw.Write((uint)(s.Length - 44)); }
public CPHDist(int ndim, GetParamVec alphaFunc, GetParamVec rateFunc, GetParam lambdaFunc, GetParamVec scaledRateFunc, double epsi) { this.ndim = ndim; this.alphaFunc = alphaFunc; this.rateFunc = rateFunc; this.lambdaFunc = lambdaFunc; this.epsi = epsi; cache_x = new double[ndim]; cache_t = 0.0; Blas.Dcopy(ndim, Alpha, cache_x); max_right = 10; prob = new double[max_right + 1]; unif = new CPHUniformization(ndim, lambdaFunc, scaledRateFunc); }
public void CopyTo(IModelParam p) { CPHParam v = p as CPHParam; if (ndim == v.ndim) { v.omega = omega; v.lambda = lambda; Blas.Dcopy(ndim, alpha, v.alpha); Blas.Dcopy(ndim, rate, v.rate); Blas.Dcopy(ndim, scaledRate, v.scaledRate); } else { throw new InvalidCastException(); } }
/// <summary> /// See <see cref="IVector.LinearCombinationIntoThis(double, IVectorView, double)"/> /// </summary> public void LinearCombinationIntoThis(double thisCoefficient, IVectorView otherVector, double otherCoefficient) { Preconditions.CheckVectorDimensions(this, otherVector); if ((otherVector is SparseVector otherSparse) && HasSameIndexer(otherSparse)) { if (thisCoefficient == 1.0) { Blas.Daxpy(values.Length, otherCoefficient, otherSparse.values, 0, 1, this.values, 0, 1); } else { BlasExtensions.Daxpby(values.Length, otherCoefficient, otherSparse.values, 0, 1, thisCoefficient, this.values, 0, 1); } } throw new SparsityPatternModifiedException( "This operation is legal only if the other vector has the same sparsity pattern"); }
/// <summary> /// See <see cref="IVector.CopySubvectorFrom(int, IVectorView, int, int)"/>. /// </summary> public void AxpySubvectorIntoThis(int destinationIndex, IVectorView sourceVector, double sourceCoefficient, int sourceIndex, int length) { Preconditions.CheckSubvectorDimensions(this, destinationIndex, length); Preconditions.CheckSubvectorDimensions(sourceVector, sourceIndex, length); if (sourceVector is Vector casted) { Blas.Daxpy(Length, sourceCoefficient, casted.data, sourceIndex, 1, this.data, destinationIndex, 1); } else { for (int i = 0; i < length; ++i) { data[i + destinationIndex] += sourceCoefficient * sourceVector[i + sourceIndex]; } } }
private void CalcProb(double t) { double dt; if (t < cache_t) { dt = t; Blas.Dcopy(ndim, Alpha, cache_x); } else { dt = t - cache_t; } int right = AllocProb(dt); unif.DoForward(dt, cache_x, right, prob); cache_t = t; }
/// <summary> /// A modified Combine version. /// result = alpha * z . (y . T) + beta * result /// </summary> /// <param name="t">The tensor used to combine y and z: t.Shape = [k, j, i]</param> /// <param name="y">A vector: y.Shape = [j]</param> /// <param name="z">A vector: z.Shape = [k]</param> /// <param name="result">A vector: result.Shape = [i], if null, will be created.</param> /// <returns>Returns result.</returns> public static Array <Real> Combine10(this Array <Real> t, Array <Real> y, Array <Real> z, Array <Real> result = null, Real alpha = 1, Real beta = 0) { if (t.Shape.Length != 3 && y.Shape.Length != 1 && z.Shape.Length != 1) { throw new ArgumentException(); } if (t.Shape[1] != y.Shape[0] && t.Shape[0] != z.Shape[0]) { throw new ArgumentException(); } if (t.Stride[2] != 1) { throw new NotImplementedException(); } if (result == null) { result = new Array <Real>(t.Shape[2]); } else { result.Scale(beta, result: result); } int strideK = z.Stride[0]; int K = z.Shape[0] * strideK + z.Offset; int strideT = t.Stride[0]; int offsetT = t.Offset; for (int k = z.Offset; k < K; k += strideK) { // result += alpha * z[k] * (y . t[k, :, :]) Blas.gemv(Order.RowMajor, Transpose.Trans, t.Shape[1], t.Shape[2], alpha * z.Values[k], t.Values, offsetT, t.Stride[1], y.Values, y.Offset, y.Stride[0], 1, result.Values, result.Offset, result.Stride[0]); offsetT += t.Stride[0]; } return(result); }
public string ToString(params string[] format) { if (format.Length == 0) { return(Blas.ArrayToString(param, "G", ",")); } else if (format.Length == 1) { return(Blas.ArrayToString(param, format[0], ",")); } else if (format.Length == param.Length) { return(Blas.ArrayToString(param, format, ",")); } else { throw new FormatException(); } }
/// <summary> /// See <see cref="IVectorView.DotProduct(IVectorView)"/>. /// </summary> public double DotProduct(IVectorView vector) { Preconditions.CheckVectorDimensions(this, vector); if (vector is Vector dense) { return(SparseBlas.Ddoti(values.Length, values, indices, 0, dense.RawData, 0)); } else if ((vector is SparseVector sparse) && HasSameIndexer(sparse)) { return(Blas.Ddot(values.Length, this.values, 0, 1, sparse.values, 0, 1)); } double sum = 0; for (int i = 0; i < values.Length; ++i) { sum += values[i] * vector[indices[i]]; } return(sum); }
//public void print() //{ // Console.Write(omega); // Console.Write(" | "); // Console.Write(Blas.intToString(shape)); // Console.Write(" | "); // Console.Write(Blas.doubleToString(alpha)); // Console.Write(" | "); // Console.Write(Blas.doubleToString(rate)); //} public string ToString(params string[] format) { string fomega; string falpha; string fshape; string frate; if (format.Length == 0) { fomega = "G"; falpha = "G"; fshape = "G"; frate = "G"; } else if (format.Length == 1) { fomega = format[0]; falpha = format[0]; fshape = format[0]; frate = format[0]; } else if (format.Length == 4) { fomega = format[0]; falpha = format[1]; fshape = format[2]; frate = format[3]; } else { throw new FormatException(); } string[] s = new string[4]; s[0] = omega.ToString(fomega); s[1] = Blas.ArrayToString(alpha, falpha, ","); s[2] = Blas.ArrayToString(shape, fshape, ","); s[3] = Blas.ArrayToString(rate, frate, ","); return(string.Join(" | ", s)); }
/// <summary> /// Performs the following operation for 0 <= j < <see cref="Order"/>, 0 <= i <= j: /// result[i, j] = <paramref name="thisCoefficient"/> * this[i, j] /// + <paramref name="otherCoefficient"/> * <paramref name="otherMatrix"/>[i, j]. /// The resulting matrix is written to a new <see cref="TriangularUpper"/> and then returned. /// </summary> /// <param name="thisCoefficient">A scalar that multiplies each entry of this <see cref="TriangularUpper"/>.</param> /// <param name="otherMatrix">A matrix with the same <see cref="Order"/> as this <see cref="TriangularUpper"/> /// instance.</param> /// <param name="otherCoefficient">A scalar that multiplies each entry of <paramref name="otherMatrix"/>.</param> /// <exception cref="NonMatchingDimensionsException">Thrown if <paramref name="otherMatrix"/> has different /// <see cref="Order"/> than this instance.</exception> public TriangularUpper LinearCombination(double thisCoefficient, TriangularUpper otherMatrix, double otherCoefficient) { Preconditions.CheckSameMatrixDimensions(this, otherMatrix); //TODO: Perhaps this should be done using mkl_malloc and BLAS copy. double[] result = new double[data.Length]; if (thisCoefficient == 1.0) { Array.Copy(this.data, result, data.Length); Blas.Daxpy(data.Length, otherCoefficient, otherMatrix.data, 0, 1, result, 0, 1); } else if (otherCoefficient == 1.0) { Array.Copy(otherMatrix.data, result, data.Length); Blas.Daxpy(data.Length, thisCoefficient, this.data, 0, 1, result, 0, 1); } else { Array.Copy(this.data, result, data.Length); BlasExtensions.Daxpby(data.Length, otherCoefficient, otherMatrix.data, 0, 1, thisCoefficient, result, 0, 1); } return(new TriangularUpper(result, NumColumns)); }
public SymmetricMatrix LinearCombination(double thisCoefficient, SymmetricMatrix otherMatrix, double otherCoefficient) { Preconditions.CheckSameMatrixDimensions(this, otherMatrix); //TODO: Perhaps this should be done using mkl_malloc and BLAS copy. double[] result = new double[data.Length]; if (thisCoefficient == 1.0) { Array.Copy(this.data, result, data.Length); Blas.Daxpy(data.Length, otherCoefficient, otherMatrix.data, 0, 1, result, 0, 1); } else if (otherCoefficient == 1.0) { Array.Copy(otherMatrix.data, result, data.Length); Blas.Daxpy(data.Length, thisCoefficient, this.data, 0, 1, result, 0, 1); } else { Array.Copy(this.data, result, data.Length); BlasExtensions.Daxpby(data.Length, otherCoefficient, otherMatrix.data, 0, 1, thisCoefficient, result, 0, 1); } return(new SymmetricMatrix(result, NumColumns, DefiniteProperty.Unknown)); }
/// <summary> /// Performs the following operation for 0 <= i < this.<see cref="Length"/>: /// result[i] = <paramref name="thisCoefficient"/> * this[i] + <paramref name="otherCoefficient"/> * /// <paramref name="otherVector"/>[i]. The resulting vector is written to a new <see cref="Vector"/> and then returned. /// </summary> /// <param name="thisCoefficient">A scalar that multiplies each entry of this <see cref="Vector"/>.</param> /// <param name="otherVector">A vector with the same <see cref="Length"/> as this <see cref="Vector"/> instance.</param> /// <param name="otherCoefficient">A scalar that multiplies each entry of <paramref name="otherVector"/>.</param> /// <exception cref="NonMatchingDimensionsException">Thrown if <paramref name="otherVector"/> has different /// <see cref="Length"/> than this.</exception> public Vector LinearCombination(double thisCoefficient, Vector otherVector, double otherCoefficient) { Preconditions.CheckVectorDimensions(this, otherVector); //TODO: Perhaps this should be done using mkl_malloc and BLAS copy. double[] result = new double[data.Length]; if (thisCoefficient == 1.0) { Array.Copy(data, result, data.Length); Blas.Daxpy(Length, otherCoefficient, otherVector.data, 0, 1, result, 0, 1); } else if (otherCoefficient == 1.0) { Array.Copy(otherVector.data, result, data.Length); Blas.Daxpy(data.Length, thisCoefficient, this.data, 0, 1, result, 0, 1); } else { Array.Copy(data, result, data.Length); BlasExtensions.Daxpby(Length, otherCoefficient, otherVector.data, 0, 1, thisCoefficient, result, 0, 1); } return(new Vector(result)); }
/// <summary> /// See <see cref="IVector.AxpySubvectorIntoThis(int, IVectorView, double, int, int)"/>. /// </summary> public void AxpySubvectorIntoThis(int destinationIndex, IVectorView sourceVector, double sourceCoefficient, int sourceIndex, int length) { //TODO: needs testing for off-by-1 bugs and extension to cases where source and destination indices are different. Preconditions.CheckSubvectorDimensions(this, destinationIndex, length); Preconditions.CheckSubvectorDimensions(sourceVector, sourceIndex, length); if ((sourceVector is SparseVector otherSparse) && HasSameIndexer(otherSparse)) { if (destinationIndex != sourceIndex) { throw new NotImplementedException(); } int start = Array.FindIndex(this.indices, x => x >= destinationIndex); int end = Array.FindIndex(this.indices, x => x >= destinationIndex + length); int sparseLength = end - start; Blas.Daxpy(sparseLength, sourceCoefficient, otherSparse.values, start, 1, this.values, start, 1); } throw new SparsityPatternModifiedException( "This operation is legal only if the other vector has the same sparsity pattern"); }
/// <summary> /// Solve the linear least squares problem A * x = b => x = inv(R) * transpose(Q) * b. /// Warning: the columns of the original matrix A must be independent for this to work. /// </summary> /// <param name="rhsVector">The right hand side vector b. It may lie outside the column space of the original matrix. Its /// <see cref="IIndexable1D.Length"/> must be equal to this.<see cref="NumRows"/>.</param> /// <exception cref="Exceptions.LapackException">Thrown if the call to LAPACK fails due to <paramref name="rhsVector"/> /// having a different <see cref="IIndexable1D.Length"/> than this.<see cref="NumRows"/>.</exception> public Vector SolveLeastSquares(Vector rhsVector) //TODO: perhaps I should use the driver routines of LAPACKE { if (NumRows < NumColumns) { throw new NotImplementedException("For now, the number of rows must be >= the number of columns"); } Preconditions.CheckSystemSolutionDimensions(NumRows, rhsVector.Length); // Least squares: x = inv(A^T * A) * A^T * b = inv(R) * Q^T * b, where b is the right hand side vector. // Step 1: c = Q^T * b. Q is m-by-m, b is m-by-1 => c is m-by-1 double[] c = rhsVector.CopyToArray(); int numRowsC = rhsVector.Length; int numColsC = 1; // rhs = m-by-1 int numReflectors = reflectorScalars.Length; int leadingDimA = numRowsC; int leadingDimC = numRowsC; LapackLeastSquares.Dormqr(MultiplicationSide.Left, TransposeMatrix.Transpose, numRowsC, numColsC, numReflectors, reflectorsAndR, 0, leadingDimA, reflectorScalars, 0, c, 0, leadingDimC); // Step 2: R * x = c, with R being m-by-n and upper trapezoidal (because m >= n). // Decomposing R: [R1; 0] * x = [c1 ; c2 ] => R1 * x = c1 => R1 * x = c1, with R1 being n-by-n, upper triangular // and stored in the factorized col major data. c1 and x are both n-by-1. The information stored in c2 is lost due to // the least squares approximation. // TODO: I do not really need to discard the extra m-n terms of c2, but I think it is unsafe to carry them around and // risk some method of Vector using the length of the internal buffer, instead of its Length propert. if (NumRows > NumColumns) { Array.Resize <double>(ref c, NumColumns); } int n = NumColumns; // Order of matrix R1 int ldR = NumRows; // R1 is stored in the upper trapezoid of a NumRows * NumColumns col major array. int incC = 1; // step in rhs array, which is the same c used for Q^T * b Blas.Dtrsv(StoredTriangle.Upper, TransposeMatrix.NoTranspose, DiagonalValues.NonUnit, n, reflectorsAndR, 0, ldR, c, 0, incC); // TODO: Check output of BLAS somehow. E.g. Zero diagonal entries will result in NaN in the result vector. return(Vector.CreateFromArray(c, false)); }
public static Array <Real> Norm2(Array <Real> a, int axis, Array <Real> result = null) { if (axis < 0) { axis = a.Shape.Length + axis; } if (result == null) { result = Zeros <Real>(GetAggregatorResultShape(a, axis, true)); } else if (result.NDim != a.NDim) { result = result.Reshape(GetAggregatorResultShape(a, axis, true)); } Array_.ElementwiseOp(a, result, (n, x, offx, incx, y, offy, incy) => { y[offy] = Blas.dot(n, x, offx, incx, x, offx, incx); }, axis); return(result); }
private static void test_cifar_multi(string filename, string weightfile) { Network net = Parser.parse_network_cfg(filename); if (string.IsNullOrEmpty(weightfile)) { Parser.load_weights(net, weightfile); } Network.set_batch_network(net, 1); float avgAcc = 0; Data.Data test = Data.Data.load_cifar10_data("Data.Data/cifar/cifar-10-batches-bin/test_batch.bin"); int i; for (i = 0; i < test.X.Rows; ++i) { Image im = new Image(32, 32, 3, test.X.Vals[i]); float[] pred = new float[10]; float[] p = Network.network_predict(net, im.Data); Blas.Axpy_cpu(10, 1, p, pred); LoadArgs.flip_image(im); p = Network.network_predict(net, im.Data); Blas.Axpy_cpu(10, 1, p, pred); int index = Utils.max_index(pred, 10); int sclass = Utils.max_index(test.Y.Vals[i], 10); if (index == sclass) { avgAcc += 1; } Console.Write($"%4d: %.2f%%\n", i, 100f * avgAcc / (i + 1)); } }
/// <summary> /// Compute the outer product of two vectors: result[i, j] = alpha * a[i] * b[j] + beta * result[i, j] /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="result"></param> /// <param name="alpha"></param> /// <param name="beta"></param> /// <returns></returns> public static Array <Real> Outer(this Array <Real> a, Array <Real> b, Array <Real> result = null, Real alpha = 1, Real beta = 0) { if (a.Shape.Length != 1 && (a.Shape.Length != 2 || a.Shape[1] != 1)) { a = a.Reshape(a.Size); } if (b.Shape.Length != 1 && (b.Shape.Length != 2 || b.Shape[1] != 1)) { b = b.Reshape(b.Size); } if (result == null) { result = new Array <Real>(a.Shape[0], b.Shape[0]); } else { if (result.Shape.Length != 2) { throw new RankException("objects are not aligned"); } if (result.Shape[0] != a.Shape[0]) { throw new RankException("objects are not aligned"); } if (result.Shape[1] != b.Shape[0]) { throw new RankException("objects are not aligned"); } // TODO: check strides ? } Blas.gemm(Order.RowMajor, Transpose.NoTrans, Transpose.Trans, result.Shape[0], result.Shape[1], 1, alpha, a.Values, a.Offset, a.Stride[0], b.Values, b.Offset, b.Stride[0], beta, result.Values, result.Offset, result.Stride[0]); return(result); }
public static Array <Real> Div(this Array <Real> a, Array <Real> b, Array <Real> result = null) { return(Array_.ElementwiseOp(a, b, result, (n, x, offsetx, incx, y, offsety, incy, z, offsetz, incz) => { if (incx == 1 && incy == 1 && incz == 1) { Blas.vdiv(n, x, offsetx, y, offsety, z, offsetz); } // TODO: else if (incx == 0) dgemv 1/x // TODO: else if (incy == 0) dgemv 1/y else { for (int i = 0; i < n; i++) { z[offsetz] = x[offsetx] / y[offsety]; offsetx += incx; offsety += incy; offsetz += incz; } } })); }
/// <summary> /// See <see cref="IVectorView.Axpy(IVectorView, double)"/>. /// </summary> public IVector Axpy(IVectorView otherVector, double otherCoefficient) { Preconditions.CheckVectorDimensions(this, otherVector); if (otherVector is SparseVector otherSparse) // In case both matrices have the exact same index arrays { if (HasSameIndexer(otherSparse)) { // Do not copy the index arrays, since they are already spread around. TODO: is this a good idea? double[] result = new double[this.values.Length]; Array.Copy(this.values, result, this.values.Length); Blas.Daxpy(values.Length, otherCoefficient, otherSparse.values, 0, 1, result, 0, 1); return(new SparseVector(Length, result, indices)); } } else if (otherVector is Vector otherDense) { double[] result = otherDense.Scale(otherCoefficient).RawData; SparseBlas.Daxpyi(this.indices.Length, 1.0, this.values, this.indices, 0, result, 0); return(Vector.CreateFromArray(result, false)); } // All entries must be processed. TODO: optimizations may be possible (e.g. only access the nnz in this vector) return(DenseStrategies.LinearCombination(this, 1.0, otherVector, otherCoefficient)); }
// markov operation public void DoBackward(double t, double[] x, int right, double[] prob) { //int right; //if (t > maxt) //{ // right = setMaxT(t); //} //else //{ // right = PoiDist.getRightBound(lambda * t, epsi); //} double weight = PoiDist.CompProb(Lambda * t, 0, right, prob); Blas.Dcopy(ndim, x, xi); Blas.Fill(ndim, x, 0.0); Blas.Daxpy(ndim, prob[0], xi, x); for (int l = 1; l <= right; l++) { Blas.Dcopy(ndim, xi, tmp); DgemvNoTrans(1.0, tmp, 0.0, xi); Blas.Daxpy(ndim, prob[l], xi, x); } Blas.Dscal(ndim, 1.0 / weight, x); }
public void DoSojournForward(double t, double[] f, double[] b, double[] h, int right, double[] prob, double[][] vc) { //int right; //if (t > maxt) //{ // right = setMaxT(t); //} //else //{ // right = PoiDist.getRightBound(lambda * t, epsi); //} double weight = PoiDist.CompProb(Lambda * t, 0, right + 1, prob); // forward and backward Blas.Fill(ndim, vc[right + 1], 0.0); Blas.Daxpy(ndim, prob[right + 1], b, vc[right + 1]); for (int l = right; l >= 1; l--) { DgemvNoTrans(1.0, vc[l + 1], 0.0, vc[l]); Blas.Daxpy(ndim, prob[l], b, vc[l]); } Blas.Dcopy(ndim, f, xi); Blas.Fill(ndim, f, 0.0); Blas.Daxpy(ndim, prob[0], xi, f); Blas.Fill(ndim * 2, h, 0.0); Dger(1.0, xi, vc[1], h); for (int l = 1; l <= right; l++) { Blas.Dcopy(ndim, xi, tmp); DgemvTrans(1.0, tmp, 0.0, xi); Blas.Daxpy(ndim, prob[l], xi, f); Dger(1.0, xi, vc[l + 1], h); } Blas.Dscal(ndim, 1.0 / weight, f); Blas.Dscal(ndim * 2, 1.0 / Lambda / weight, h); }
/// <summary> /// See <see cref="IVectorView.Norm2"/> /// </summary> public double Norm2() => Blas.Dnrm2(Length, data, 0, 1);
public void AxpyIntoThis(SymmetricMatrix otherMatrix, double otherCoefficient) { Preconditions.CheckSameMatrixDimensions(this, otherMatrix); Blas.Daxpy(data.Length, otherCoefficient, otherMatrix.data, 0, 1, this.data, 0, 1); this.Definiteness = DefiniteProperty.Unknown; }
/// <summary> /// Calculates the dot (or inner/scalar) product of this vector with <paramref name="vector"/>: /// result = sum over all i of this[i] * <paramref name="vector"/>[i]). /// </summary> /// <param name="vector">A vector with the same <see cref="Length"/> as this.</param> public double DotProduct(Vector vector) { Preconditions.CheckVectorDimensions(this, vector); return(Blas.Ddot(Length, this.data, 0, 1, vector.data, 0, 1)); }
/// <summary> /// Matrix multiplication. /// Returns: alpha * dot(a, b) + beta * result /// Ie with default value: dot(a, b) /// </summary> /// <remarks> /// For 2-D arrays it is equivalent to matrix multiplication, /// and for 1-D arrays to inner product of vectors (without complex conjugation). /// For N dimensions it is a sum product over the last axis of a and the second-to-last of b: /// dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m]) /// `TensorDot` provides more control for N-dim array multiplication. /// </remarks> public static Array <Real> Dot(this Array <Real> a, Array <Real> b, Array <Real> result = null, Real alpha = 1, Real beta = 0, bool transA = false, bool transB = false) { if (transA) { if (a.Shape.Length == 1) { if (b.Shape.Length == 1) { if (transB) { return(a.Dot(b, result, alpha, beta)); } else { return(a.VectorDot(b)); } } if (b.Shape.Length != 2) { throw new NotImplementedException(); } return(b.Dot(a, result, alpha, beta, transA: !transB, transB: false)); } else { a = a.T; // TODO: optimize => avoid creating new shape, stride, ... //if (b.Shape.Length == 1 && !transB) b = b.Reshape(1, b.Shape[0]); } transA = false; } if (transB) { if (b.Shape.Length == 1) { if (a.Shape.Length == 1) { if (transA) { throw new NotImplementedException(); } return(a.Outer(b, result: result, alpha: alpha, beta: 0)); } throw new NotImplementedException(); //if (a.Shape.Length != 2) throw new NotImplementedException(); //if (a.IsTransposed()) //{ // a = a.T; // transA = !transA; //} //result = new Array<Real>(transA ? a.Shape[1] : a.Shape[0], b.Shape[0]); // TODO: result != null //Blas.gemm(Order.RowMajor, transA ? Transpose.Trans : Transpose.NoTrans, Transpose.NoTrans, // result.Shape[0], result.Shape[1], 1, // alpha, // a.Values, a.Offset, a.Stride[0], // b.Values, b.Offset, b.Stride[0], // beta, // result.Values, result.Offset, result.Stride[0]); //return result; } else { b = b.T; // TODO: optimize => avoid creating new shape, stride, ... } transB = false; } // TODO: check alpha & beta if (a.Shape.Length == 0) { return(b.Scale(a.Values[a.Offset])); } if (b.Shape.Length == 0) { return(a.Scale(b.Values[b.Offset])); } if (a.Shape.Length == 1) // vector x tensor { if (b.Shape.Length == 1) // vector x vector { if (a.Shape[0] != b.Shape[0]) { throw AssertArray.BadRank("objects are not aligned: [{0}] dot [{1}]", a.Shape[0], b.Shape[0]); } if (result == null) { result = new Array <Real>(); } else { if (result.Shape.Length != 0) { throw AssertArray.BadRank("objects are not aligned"); } } result.Values[result.Offset] = beta * result.Values[result.Offset] + alpha * Blas.dot(a.Shape[0], a.Values, a.Offset, a.Stride[0], b.Values, b.Offset, b.Stride[0]); return(result); } else if (b.Shape.Length == 2) // vector x matrix { if (a.Shape[0] != b.Shape[0]) { throw new RankException("objects are not aligned"); } if (result == null) { result = new Array <Real>(b.Shape[1]); } else { if (result.Shape.Length != 1) { throw new RankException("objects are not aligned"); } if (result.Shape[0] != b.Shape[1]) { throw new RankException("objects are not aligned"); } } // dgemv computes matrix x vector => result = M.T.dot(v.T).T transB = !transB; if (b.IsTransposed()) { transB = !transB; b = b.T; } // y:= alpha * A' * x + beta * y Blas.gemv(Order.RowMajor, transB ? Transpose.Trans : Transpose.NoTrans, b.Shape[0], b.Shape[1], alpha, b.Values, b.Offset, b.Stride[0], a.Values, a.Offset, a.Stride[0], beta, result.Values, result.Offset, result.Stride[0]); return(result); } else if (b.Shape.Length == 3) // vector x tensor3 { // TODO: beta ? if (a.Shape[0] != b.Shape[1]) { throw new RankException("objects are not aligned"); } if (result == null) { result = new Array <Real>(b.Shape[0], b.Shape[2]); } else { if (result.Shape[0] != b.Shape[0]) { throw new RankException("objects are not aligned"); } if (result.Shape[1] != b.Shape[2]) { throw new RankException("objects are not aligned"); } } var offsetk = b.Offset; var k_0 = result.Offset; for (var k = 0; k < result.Shape[0]; k++) // result.Shape[0] == b.Shape[0] { var offsetm = offsetk; var k_m = k_0; for (var m = 0; m < result.Shape[1]; m++) // result.Shape[1] == b.Shape[2] { result.Values[k_m] = alpha * Blas.dot(a.Shape[0], a.Values, a.Offset, a.Stride[0], b.Values, offsetm, b.Stride[1]); // a.Shape[axis] == b.Shape[1]; offsetm += b.Stride[2]; k_m += result.Stride[1]; } offsetk += b.Stride[0]; k_0 += result.Stride[0]; } return(result); } throw new NotImplementedException(); } else if (b.Shape.Length == 1) // tensor x vector { if (a.Shape.Length == 2) // matrix x vector { if (a.Shape[1] != b.Shape[0]) { throw new RankException("objects are not aligned"); } if (result == null) { result = new Array <Real>(a.Shape[0]); } else { if (result.Shape.Length != b.Shape.Length) { throw new RankException("objects are not aligned"); } if (result.Shape[0] != a.Shape[0]) { throw new RankException("objects are not aligned"); } // TODO: check strides } if ((a.Flags & Flags.Transposed) != 0) { transA = !transA; a = a.T; } // y:= A*x + beta*y if (a.Stride[1] == 1) { Blas.gemv(Order.RowMajor, transA ? Transpose.Trans : Transpose.NoTrans, a.Shape[0], a.Shape[1], alpha, a.Values, a.Offset, a.Stride[0], b.Values, b.Offset, b.Stride[0], beta, result.Values, result.Offset, result.Stride[0]); } else { // y *= beta if (beta != 1) { result.Scale(beta, result: result); } int offB = b.Offset; int offA = a.Offset; for (int j = 0; j < b.Shape[0]; ++j) { Blas.axpy(a.Shape[0], alpha * b.Values[offB], a.Values, offA, a.Stride[0], result.Values, result.Offset, result.Stride[0]); offB += b.Stride[0]; offA += a.Stride[1]; } } return(result); } else if (a.Shape.Length == 3) // tensor x vector = mat { if (a.Shape[2] != b.Shape[0]) { throw new RankException("objects are not aligned"); } if (result == null) { result = new Array <Real>(a.Shape[0], a.Shape[1]); } else if (result.Shape[0] != a.Shape[0] || result.Shape[1] != a.Shape[1]) { throw new RankException("objects are not aligned"); } var offsetk = a.Offset; var offsetRes = result.Offset; for (var k = 0; k < result.Shape[0]; k++) { var offsetj = offsetk; for (var j = 0; j < result.Shape[1]; j++) { result.Values[offsetRes] = alpha * Blas.dot(a.Shape[2], a.Values, offsetj, a.Stride[2], b.Values, b.Offset, b.Stride[0]); offsetj += a.Stride[1]; offsetRes += result.Stride[1]; } offsetk += a.Stride[0]; } return(result); } throw new NotImplementedException(); } else if (a.Shape.Length == 2 && b.Shape.Length == 2) // matrix x matrix { if (a.Shape[1] != b.Shape[0]) { throw AssertArray.BadRank("objects are not aligned: [{0}, {1}] dot [{2}, {3}]", a.Shape[0], a.Shape[1], b.Shape[0], b.Shape[1]); } if (result == null) { result = new Array <Real>(a.Shape[0], b.Shape[1]); } else { if (result.Shape[0] != a.Shape[0] || result.Shape[1] != b.Shape[1]) { throw AssertArray.BadRank("result target have incorrect shape: [{0}, {1}] instead of [{2}, {3}].", result.Shape[0], result.Shape[1], a.Shape[0], b.Shape[1]); } // TODO: check strides } var m = a.Shape[0]; var n = b.Shape[1]; var k = a.Shape[1]; if ((a.Flags & Flags.Transposed) != 0) { transA = !transA; a = a.T; } if ((b.Flags & Flags.Transposed) != 0) { transB = !transB; b = b.T; } // C:= alpha * op(A) * op(B) + beta * C Blas.gemm(Order.RowMajor, transA ? Transpose.Trans : Transpose.NoTrans, transB ? Transpose.Trans : Transpose.NoTrans, m, n, k, alpha, a.Values, a.Offset, a.Stride[0], b.Values, b.Offset, b.Stride[0], beta, result.Values, result.Offset, result.Stride[0]); return(result); } // tensor x tensor throw new NotImplementedException(); }
/// <summary> /// Performs the following operation for 0 <= i < this.<see cref="Length"/>: /// this[i] = <paramref name="otherCoefficient"/> * <paramref name="otherVector"/>[i] + this[i]. /// The resulting vector overwrites the entries of this <see cref="Vector"/> instance. /// </summary> /// <param name="otherVector">A vector with the same <see cref="Length"/> as this <see cref="Vector"/> instance.</param> /// <param name="otherCoefficient">A scalar that multiplies each entry of <paramref name="otherVector"/>.</param> /// <exception cref="NonMatchingDimensionsException">Thrown if <paramref name="otherVector"/> has different /// <see cref="Length"/> than this.</exception> public void AxpyIntoThis(Vector otherVector, double otherCoefficient) { Preconditions.CheckVectorDimensions(this, otherVector); Blas.Daxpy(Length, otherCoefficient, otherVector.data, 0, 1, this.data, 0, 1); }
/// <summary> /// See <see cref="IVector.ScaleIntoThis(double)"/>. /// </summary> public void ScaleIntoThis(double scalar) => Blas.Dscal(Length, scalar, data, 0, 1);