func calike(a, b complex128) bool { switch { case cmplx.IsInf(a) && cmplx.IsInf(b): return true case cmplx.IsNaN(a) && cmplx.IsNaN(b): return true } return a == b }
/* General matrix-matrix product. (L3) PURPOSE Computes C := alpha*A*B + beta*C if transA = PNoTrans and transB = PNoTrans. C := alpha*A^T*B + beta*C if transA = PTrans and transB = PNoTrans. C := alpha*A^H*B + beta*C if transA = PConjTrans and transB = PNoTrans. C := alpha*A*B^T + beta*C if transA = PNoTrans and transB = PTrans. C := alpha*A^T*B^T + beta*C if transA = PTrans and transB = PTrans. C := alpha*A^H*B^T + beta*C if transA = PConjTrans and transB = PTrans. C := alpha*A*B^H + beta*C if transA = PNoTrans and transB = PConjTrans. C := alpha*A^T*B^H + beta*C if transA = PTrans and transB = PConjTrans. C := alpha*A^H*B^H + beta*C if transA = PConjTrans and transB = PConjTrans. The number of rows of the matrix product is m. The number of columns is n. The inner dimension is k. If k=0, this reduces to C := beta*C. ARGUMENTS A float or complex matrix, m*k B float or complex matrix, k*n C float or complex matrix, m*n alpha number (float or complex singleton matrix) beta number (float or complex singleton matrix) OPTIONS transA PNoTrans, PTrans or PConjTrans transB PNoTrans, PTrans or PConjTrans m integer. If negative, the default value is used. The default value is m = A.Rows of if transA != PNoTrans m = A.Cols. n integer. If negative, the default value is used. The default value is n = (transB == PNoTrans) ? B.Cols : B.Rows. k integer. If negative, the default value is used. The default value is k=A.Cols or if transA != PNoTrans) k = A.Rows, transA=PNoTrans. If the default value is used it should also be equal to (transB == PNoTrans) ? B.Rows : B.Cols. ldA nonnegative integer. ldA >= max(1,m) of if transA != NoTrans max(1,k). If zero, the default value is used. ldB nonnegative integer. ldB >= max(1,k) or if transB != NoTrans max(1,n). If zero, the default value is used. ldC nonnegative integer. ldC >= max(1,m). If zero, the default value is used. offsetA nonnegative integer offsetB nonnegative integer offsetC nonnegative integer; */ func Gemm(A, B, C matrix.Matrix, alpha, beta matrix.Scalar, opts ...linalg.Option) (err error) { params, e := linalg.GetParameters(opts...) if e != nil { err = e return } ind := linalg.GetIndexOpts(opts...) err = check_level3_func(ind, fgemm, A, B, C, params) if err != nil { return } if ind.M == 0 || ind.N == 0 { return } if !matrix.EqualTypes(A, B, C) { return errors.New("Parameters not of same type") } switch A.(type) { case *matrix.FloatMatrix: Aa := A.FloatArray() Ba := B.FloatArray() Ca := C.FloatArray() aval := alpha.Float() bval := beta.Float() if math.IsNaN(aval) || math.IsNaN(bval) { return errors.New("alpha or beta not a number") } transB := linalg.ParamString(params.TransB) transA := linalg.ParamString(params.TransA) dgemm(transA, transB, ind.M, ind.N, ind.K, aval, Aa[ind.OffsetA:], ind.LDa, Ba[ind.OffsetB:], ind.LDb, bval, Ca[ind.OffsetC:], ind.LDc) case *matrix.ComplexMatrix: Aa := A.ComplexArray() Ba := B.ComplexArray() Ca := C.ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return errors.New("alpha not a number") } bval := beta.Complex() if cmplx.IsNaN(bval) { return errors.New("beta not a number") } transB := linalg.ParamString(params.TransB) transA := linalg.ParamString(params.TransA) zgemm(transA, transB, ind.M, ind.N, ind.K, aval, Aa[ind.OffsetA:], ind.LDa, Ba[ind.OffsetB:], ind.LDb, bval, Ca[ind.OffsetC:], ind.LDc) default: return errors.New("Unknown type, not implemented") } return }
func FlexEqual(x, y interface{}) bool { var isfloat, iscomplex bool var xf, yf float64 var xc, yc complex128 switch x := x.(type) { case float32: if _, ok := y.(float32); !ok { return false } xf, yf = float64(x), float64(y.(float32)) isfloat = true case float64: if _, ok := y.(float64); !ok { return false } xf, yf = float64(x), y.(float64) isfloat = true case complex64: if _, ok := y.(complex64); !ok { return false } xc, yc = complex128(x), complex128(y.(complex64)) iscomplex = true case complex128: if _, ok := y.(complex128); !ok { return false } xc, yc = complex128(x), y.(complex128) iscomplex = true } if isfloat { switch { case math.IsNaN(xf) && math.IsNaN(yf): return true case math.IsInf(xf, 1) && math.IsInf(yf, 1): return true case math.IsInf(xf, -1) && math.IsInf(yf, -1): return true } } if iscomplex { switch { case cmplx.IsNaN(xc) && cmplx.IsNaN(yc): return true case cmplx.IsInf(xc) && cmplx.IsInf(yc): return true } } return reflect.DeepEqual(x, y) }
/* Matrix-matrix product where one matrix is symmetric. (L3) Computes C := alpha*A*B + beta*C, if side is PLeft C := alpha*B*A + beta*C, if side is PRight C is m by n and A is real symmetric. ARGUMENTS A float or complex matrix B float or complex matrix. C float m*n matrix. alpha number (float). beta number (float). OPTIONS side PLeft or PRight' uplo PLower or PUpper m integer. If negative, the default value is used. If the default value is used and side = PLeft, then m must be equal to A.Rows and A.Cols. n integer. If negative, the default value is used. If the default value is used and side = PRight, then must be equal to A.Rows and A.Cols. ldA nonnegative integer. ldA >= max(1, m) or if side == PRight ldA >= max(1, n). If zero, the default value is used. ldB nonnegative integer. ldB >= max(1,n) or if side == PRight ldB >= max(1, m). If zero, the default value is used. ldC nonnegative integer. ldC >= max(1,m). If zero, the default value is used. offsetA nonnegative integer offsetB nonnegative integer offsetC nonnegative integer */ func Symm(A, B, C matrix.Matrix, alpha, beta matrix.Scalar, opts ...linalg.Option) (err error) { params, e := linalg.GetParameters(opts...) if e != nil { err = e return } ind := linalg.GetIndexOpts(opts...) err = check_level3_func(ind, fsymm, A, B, C, params) if err != nil { return } if ind.M == 0 || ind.N == 0 { return } if !matrix.EqualTypes(A, B, C) { return onError("Parameters not of same type") } switch A.(type) { case *matrix.FloatMatrix: Aa := A.(*matrix.FloatMatrix).FloatArray() Ba := B.(*matrix.FloatMatrix).FloatArray() Ca := C.(*matrix.FloatMatrix).FloatArray() aval := alpha.Float() bval := beta.Float() if math.IsNaN(aval) || math.IsNaN(bval) { return onError("alpha or beta not a number") } uplo := linalg.ParamString(params.Uplo) side := linalg.ParamString(params.Side) dsymm(side, uplo, ind.M, ind.N, aval, Aa[ind.OffsetA:], ind.LDa, Ba[ind.OffsetB:], ind.LDb, bval, Ca[ind.OffsetC:], ind.LDc) case *matrix.ComplexMatrix: Aa := A.(*matrix.ComplexMatrix).ComplexArray() Ba := B.(*matrix.ComplexMatrix).ComplexArray() Ca := C.(*matrix.ComplexMatrix).ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return onError("alpha not a number") } bval := beta.Complex() if cmplx.IsNaN(bval) { return onError("beta not a number") } uplo := linalg.ParamString(params.Uplo) side := linalg.ParamString(params.Side) zhemm(side, uplo, ind.M, ind.N, aval, Aa[ind.OffsetA:], ind.LDa, Ba[ind.OffsetB:], ind.LDb, bval, Ca[ind.OffsetC:], ind.LDc) default: return onError("Unknown type, not implemented") } return }
/* Rank-k update of symmetric matrix. (L3) Syrk(A, C, alpha=1.0, beta=0.0, uplo=PLower, trans=PNoTrans, n=-1, k=-1, ldA=max(1,A.Rows), ldC=max(1,C.Rows), offsetA=0, offsetB=0) PURPOSE C := alpha*A*A^T + beta*C, if trans is PNoTrans C := alpha*A^T*A + beta*C, if trans is PTrans C := alpha*A^H*A + beta*C, if trans is PConjTrans C is symmetric (real or complex) of order n. The inner dimension of the matrix product is k. If k=0 this is interpreted as C := beta*C. ARGUMENTS A float or complex n*k matrix C float or complex n*n matrix. Must have the same type as A. alpha number (float or complex singleton matrix). Complex alpha is only allowed if A is complex. beta number (float or complex singleton matrix). Complex beta is only allowed if A is complex. OPTIONS uplo PLower or PUpper trans PNoTrans, PTrans or PConjTrans n integer. If negative, the default value is used. The default value is n = A.Rows of if trans != PNoTrans) n = A.Cols. k integer. If negative, the default value is used. The default value is k = A.Cols or if trans != PNoTrans k = A.Rows. ldA nonnegative integer. ldA >= max(1, n) or if trans != PNoTrans max(1, k). If zero, the default value [max(1, A.Rows)] is used. ldC nonnegative integer. ldC >= max(1,n). If zero, the default value is used. offsetA nonnegative integer offsetC nonnegative integer; */ func Syrk(A, C matrix.Matrix, alpha, beta matrix.Scalar, opts ...linalg.Option) (err error) { params, e := linalg.GetParameters(opts...) if e != nil { err = e return } ind := linalg.GetIndexOpts(opts...) err = check_level3_func(ind, fsyrk, A, nil, C, params) if e != nil || err != nil { return } if !matrix.EqualTypes(A, C) { return errors.New("Parameters not of same type") } switch A.(type) { case *matrix.FloatMatrix: Aa := A.FloatArray() Ca := C.FloatArray() aval := alpha.Float() bval := beta.Float() if math.IsNaN(aval) || math.IsNaN(bval) { return errors.New("alpha or beta not a number") } uplo := linalg.ParamString(params.Uplo) trans := linalg.ParamString(params.Trans) dsyrk(uplo, trans, ind.N, ind.K, aval, Aa[ind.OffsetA:], ind.LDa, bval, Ca[ind.OffsetC:], ind.LDc) case *matrix.ComplexMatrix: Aa := A.ComplexArray() Ca := C.ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return errors.New("alpha not a number") } bval := beta.Complex() if cmplx.IsNaN(bval) { return errors.New("beta not a number") } uplo := linalg.ParamString(params.Uplo) trans := linalg.ParamString(params.Trans) zsyrk(uplo, trans, ind.N, ind.K, aval, Aa[ind.OffsetA:], ind.LDa, bval, Ca[ind.OffsetC:], ind.LDc) default: return errors.New("Unknown type, not implemented") } return }
func formatSolutions(x1, x2 complex128) string { exactlyOneSolution := false if cmplx.IsNaN(x1) && cmplx.IsNaN(x2) { return noSolution } if cmplx.IsNaN(x1) { exactlyOneSolution = true x1 = x2 } else if cmplx.IsNaN(x2) || numbers.EqualComplex(x1, x2) { exactlyOneSolution = true } if exactlyOneSolution { return fmt.Sprintf(oneSolution, formatComplex(x1)) } return fmt.Sprintf(twoSolutions, formatComplex(x1), formatComplex(x2)) }
func mandelbrot(c complex128) uint16 { var z complex128 for i := 0; i < Iterations; i++ { z = z*z + c if cmplx.IsNaN(z) { return uint16(i) } } return Iterations }
/* Solution of a triangular system of equations with multiple righthand sides. (L3) Trsm(A, B, alpha, side=PLeft, uplo=PLower, transA=PNoTrans, diag=PNonUnit, m=-1, n=-1, ldA=max(1,A.Rows), ldB=max(1,B.Rows), offsetA=0, offsetB=0) Computes B := alpha*A^{-1}*B if transA is PNoTrans and side = PLeft B := alpha*B*A^{-1} if transA is PNoTrans and side = PRight B := alpha*A^{-T}*B if transA is PTrans and side = PLeft B := alpha*B*A^{-T} if transA is PTrans and side = PRight B := alpha*A^{-H}*B if transA is PConjTrans and side = PLeft B := alpha*B*A^{-H} if transA is PConjTrans and side = PRight B is m by n and A is triangular. The code does not verify whether A is nonsingular. ARGUMENTS A float or complex matrix. B float or complex matrix. Must have the same type as A. alpha number (float or complex). Complex alpha is only allowed if A is complex. OPTIONS side PLeft or PRight uplo PLower or PUpper transA PNoTrans or PTrans diag PNonUnit or PUnit m integer. If negative, the default value is used. The default value is m = A.Rows or if side == PRight m = B.Rows If the default value is used and side is PLeft, m must be equal to A.Cols. n integer. If negative, the default value is used. The default value is n = B.Cols or if side )= PRight n = A.Rows. If the default value is used and side is PRight, n must be equal to A.Cols. ldA nonnegative integer. ldA >= max(1,m) of if side == PRight lda >= max(1,n). If zero, the default value is used. ldB nonnegative integer. ldB >= max(1,m). If zero, the default value is used. offsetA nonnegative integer offsetB nonnegative integer */ func Trsm(A, B matrix.Matrix, alpha matrix.Scalar, opts ...linalg.Option) (err error) { params, e := linalg.GetParameters(opts...) if e != nil { err = e return } ind := linalg.GetIndexOpts(opts...) err = check_level3_func(ind, ftrsm, A, B, nil, params) if err != nil { return } if !matrix.EqualTypes(A, B) { return errors.New("Parameters not of same type") } switch A.(type) { case *matrix.FloatMatrix: Aa := A.FloatArray() Ba := B.FloatArray() aval := alpha.Float() if math.IsNaN(aval) { return errors.New("alpha or beta not a number") } uplo := linalg.ParamString(params.Uplo) transA := linalg.ParamString(params.TransA) side := linalg.ParamString(params.Side) diag := linalg.ParamString(params.Diag) dtrsm(side, uplo, transA, diag, ind.M, ind.N, aval, Aa[ind.OffsetA:], ind.LDa, Ba[ind.OffsetB:], ind.LDb) case *matrix.ComplexMatrix: Aa := A.ComplexArray() Ba := B.ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return errors.New("alpha not a number") } uplo := linalg.ParamString(params.Uplo) transA := linalg.ParamString(params.TransA) side := linalg.ParamString(params.Side) diag := linalg.ParamString(params.Diag) ztrsm(side, uplo, transA, diag, ind.M, ind.N, aval, Aa[ind.OffsetA:], ind.LDa, Ba[ind.OffsetB:], ind.LDb) default: return errors.New("Unknown type, not implemented") } return }
/* General rank-1 update. (L2) Ger(X, Y, A, alpha=1.0, m=A.Rows, n=A.Cols, incx=1, incy=1, ldA=max(1,A.Rows), offsetx=0, offsety=0, offsetA=0) COMPUTES A := A + alpha*X*Y^H with A m*n, real or complex. ARGUMENTS X float or complex matrix. Y float or complex matrix. Must have the same type as X. A float or complex matrix. Must have the same type as X. alpha number (float or complex singleton matrix). OPTIONS m integer. If negative, the default value is used. n integer. If negative, the default value is used. incx nonzero integer incy nonzero integer ldA nonnegative integer. ldA >= max(1,m). If zero, the default value is used. offsetx nonnegative integer offsety nonnegative integer offsetA nonnegative integer; */ func Ger(X, Y, A matrix.Matrix, alpha matrix.Scalar, opts ...linalg.Option) (err error) { var params *linalg.Parameters if !matrix.EqualTypes(A, X, Y) { err = errors.New("Parameters not of same type") return } params, err = linalg.GetParameters(opts...) if err != nil { return } ind := linalg.GetIndexOpts(opts...) err = check_level2_func(ind, fger, X, Y, A, params) if err != nil { return } if ind.N == 0 || ind.M == 0 { return } switch X.(type) { case *matrix.FloatMatrix: Xa := X.FloatArray() Ya := Y.FloatArray() Aa := A.FloatArray() aval := alpha.Float() if math.IsNaN(aval) { return errors.New("alpha not a number") } dger(ind.M, ind.N, aval, Xa[ind.OffsetX:], ind.IncX, Ya[ind.OffsetY:], ind.IncY, Aa[ind.OffsetA:], ind.LDa) case *matrix.ComplexMatrix: Xa := X.ComplexArray() Ya := Y.ComplexArray() Aa := A.ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return errors.New("alpha not a number") } zgerc(ind.M, ind.N, aval, Xa[ind.OffsetX:], ind.IncX, Ya[ind.OffsetY:], ind.IncY, Aa[ind.OffsetA:], ind.LDa) default: return errors.New("Unknown type, not implemented") } return }
/* Symmetric rank-2 update. her2(x, y, A, uplo='L', alpha=1.0, n=A.size[0], incx=1, incy=1, ldA=max(1,A.size[0]), offsetx=0, offsety=0, offsetA=0) PURPOSE Computes A := A + alpha*(x*y^T + y*x^T) with A real symmetric or complex hermitian matix of order n. ARGUMENTS x float or complex matrix y float or complex matrix A float or complex matrix alpha float or complex singleton value OPTIONS: uplo 'L' or 'U' n integer. If negative, the default value is used. incx nonzero integer incy nonzero integer ldA nonnegative integer. ldA >= max(1,n). If zero the default value is used. offsetx nonnegative integer offsety nonnegative integer offsetA nonnegative integer; */ func Her2(X, Y, A matrix.Matrix, alpha matrix.Scalar, opts ...linalg.Option) (err error) { var params *linalg.Parameters params, err = linalg.GetParameters(opts...) if err != nil { return } ind := linalg.GetIndexOpts(opts...) err = check_level2_func(ind, fsyr2, X, Y, A, params) if err != nil { return } if !matrix.EqualTypes(A, X, Y) { return errors.New("Parameters not of same type") } switch X.(type) { case *matrix.FloatMatrix: Xa := X.FloatArray() Ya := X.FloatArray() Aa := A.FloatArray() aval := alpha.Float() if math.IsNaN(aval) { return errors.New("alpha not a number") } uplo := linalg.ParamString(params.Uplo) dsyr2(uplo, ind.N, aval, Xa[ind.OffsetX:], ind.IncX, Ya[ind.OffsetY:], ind.IncY, Aa[ind.OffsetA:], ind.LDa) case *matrix.ComplexMatrix: Xa := X.ComplexArray() Ya := X.ComplexArray() Aa := A.ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return errors.New("alpha not a number") } uplo := linalg.ParamString(params.Uplo) zher2(uplo, ind.N, aval, Xa[ind.OffsetX:], ind.IncX, Ya[ind.OffsetY:], ind.IncY, Aa[ind.OffsetA:], ind.LDa) //zher(uplo, ind.N, aval, Xa[ind.OffsetX:], ind.IncX, // Aa[ind.OffsetA:], ind.LDa) default: return errors.New("Unknown type, not implemented") } return }
// Constant times a vector plus a vector (Y := alpha*X+Y). // // ARGUMENTS // X float or complex matrix // Y float or complex matrix. Must have the same type as X. // alpha number (float or complex singleton matrix). Complex alpha is only // allowed if x is complex. // // OPTIONS // n integer. If n<0, the default value of n is used. // The default value is equal to 1+(len(x)-offsetx-1)/incx // or 0 if len(x) >= offsetx+1 // incx nonzero integer // incy nonzero integer // offsetx nonnegative integer // offsety nonnegative integer; // func Axpy(X, Y matrix.Matrix, alpha matrix.Scalar, opts ...linalg.Option) (err error) { ind := linalg.GetIndexOpts(opts...) err = check_level1_func(ind, faxpy, X, Y) if err != nil { return } if ind.Nx == 0 { return } sameType := matrix.EqualTypes(X, Y) if ! sameType { err = errors.New("arrays not same type") return } switch X.(type) { case *matrix.ComplexMatrix: Xa := X.ComplexArray() Ya := Y.ComplexArray() aval := alpha.Complex() if cmplx.IsNaN(aval) { return errors.New("alpha not complex value") } zaxpy(ind.Nx, aval, Xa[ind.OffsetX:], ind.IncX, Ya[ind.OffsetY:], ind.IncY) case *matrix.FloatMatrix: Xa := X.FloatArray() Ya := Y.FloatArray() aval := alpha.Float() if math.IsNaN(aval) { return errors.New("alpha not float value") } daxpy(ind.Nx, aval, Xa[ind.OffsetX:], ind.IncX, Ya[ind.OffsetY:], ind.IncY) default: err = errors.New("not implemented for parameter types", ) } return }