func (m *Matrix) AggregateProcedure(aggr Float64Float64Func, f Float64Func, cond Float64Procedure) float64 { if m.Size() == 0 { return math.NaN() } var a float64 n := runtime.GOMAXPROCS(-1) if n > 1 && m.Rows()*m.Columns() > common.MatrixThreshold { n = common.Min(n, m.Rows()) ch := make(chan float64, n) k := m.Rows() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = m.Rows() } else { idx1 = idx0 + k } go func() { elem := m.GetQuick(idx0, 0) b := 0 if cond(elem) { b = aggr(b, f(elem)) } d := 1 for r := idx0; r < idx1; r++ { for c := d; c < m.Columns(); c++ { elem = m.GetQuick(r, c) if cond(elem) { b = aggr(b, f(elem)) } } d = 0 } ch <- b }() } a = <-ch for j := 1; j < n; j++ { a = aggr(a, <-ch) } } else { a := 0.0 elem := m.GetQuick(0, 0) if cond(elem) { a = aggr(a, f(elem)) } d := 1 // First cell already done. for r := 0; r < m.Rows(); r++ { for c := d; c < m.Columns(); c++ { elem = m.GetQuick(r, c) if cond(elem) { a = aggr(a, f(elem)) } } d = 0 } } return a }
func (m *Matrix) AssignFunc(f Float64Func) *Matrix { n := runtime.GOMAXPROCS(-1) if n > 1 && m.Rows()*m.Columns() > common.MatrixThreshold { n = common.Min(n, m.Rows()) done := make(chan bool, n) k := m.Rows() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = m.Rows() } else { idx1 = idx0 + k } go func() { for r := idx0; r < idx1; r++ { for c := 0; c < m.Columns(); c++ { m.SetQuick(r, c, f(m.GetQuick(r, c))) } } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for r := 0; r < m.Rows(); r++ { for c := 0; c < m.Columns(); c++ { m.SetQuick(r, c, f(m.GetQuick(r, c))) } } } return m }
// Sets all cells to the state specified by "values". "values" // is required to have the same number of cells as the receiver. // // The values are copied. So subsequent changes in "values" are not // reflected in the matrix, and vice-versa. func (v *Vector) AssignArray(values []float64) (*Vector, error) { if len(values) != v.Size() { return v, fmt.Errorf("Must have same number of cells: length=%d size()=%d", len(values), v.Size()) } n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { v.SetQuick(i, values[i]) } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for i, val := range values { v.SetQuick(i, val) } } return v, nil }
// Assigns the result of a function to each cell; x[i] = f(x[i]). func (v *Vector) AssignFunc(f Float64Func) *Vector { n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { v.SetQuick(i, f(v.GetQuick(i))) } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for i := 0; i < v.Size(); i++ { v.SetQuick(i, f(v.GetQuick(i))) } } return v }
// Fills the cell values into the specified 1-dimensional array. // The values are copied. So subsequent changes in <tt>values</tt> are not // reflected in the matrix, and vice-versa. The returned array // values has the form: // for i:=0; i < Size; i++ {values[i] = Get(i)} func (v *Vector) FillArray(values []float64) error { if len(values) < v.Size() { return fmt.Errorf("values too small") } n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { values[i] = v.GetQuick(i) } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for i := 0; i < v.Size(); i++ { values[i] = v.GetQuick(i) } } return nil }
// Return the minimum value of this matrix together with its location. func (v *Vector) MinLocation() (float64, int) { var location int var minValue float64 n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) c := make(chan vectorElement, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { loc := idx0 min := v.GetQuick(loc) for i := idx0 + 1; i < idx1; i++ { elem := v.GetQuick(i) if min > elem { min = elem loc = i } } c <- vectorElement{min, loc} }() } vl0 := <-c minValue = vl0.value location = vl0.location for j := 1; j < n; j++ { vl := <-c if minValue > vl.value { minValue = vl.value location = vl.location } } } else { location = 0 minValue = v.GetQuick(location) for i := 1; i < v.Size(); i++ { elem := v.GetQuick(i) if minValue > elem { minValue = elem location = i } } } return minValue, location }
// Returns the dot product of two vectors x and y, which is // Sum(x[i]*y[i]). Where x == this. Operates on cells at // indexes from .. Min(Size(), y.Size(),from+length)-1. func (v *Vector) ZDotProductRange(y Vec, from, length int) float64 { if from < 0 || length <= 0 { return 0 } tail := from + length if v.Size() < tail { tail = v.Size() } if y.Size() < tail { tail = y.Size() } length = tail - from var sum float64 n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, length) c := make(chan float64, n) k := length / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = length } else { idx1 = idx0 + k } go func() { s := 0.0 for i := idx0; i < idx1; i++ { idx := k + from s += v.GetQuick(idx) * y.GetQuick(idx) } c <- s }() } sum = <-c for j := 1; j < n; j++ { sum += <-c } } else { sum = 0.0 i := tail - 1 for k := 0; k < length; i-- { sum += v.GetQuick(i) * y.GetQuick(i) k++ } } return sum }
func (m *Matrix) AggregateMatrix(other Mat, aggr Float64Float64Func, f Float64Float64Func) (float64, error) { err := m.checkShape(other) if err != nil { return math.NaN(), err } if m.Size() == 0 { return math.NaN(), nil } a := 0.0 n := runtime.GOMAXPROCS(-1) if n > 1 && m.Rows()*m.Columns() > common.MatrixThreshold { n = common.Min(n, m.Rows()) ch := make(chan float64, n) k := m.Rows() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = m.Rows() } else { idx1 = idx0 + k } go func() { a := f(m.GetQuick(idx0, 0), other.GetQuick(idx0, 0)) d := 1 for r := idx0; r < idx1; r++ { for c := d; c < m.Columns(); c++ { a = aggr(a, f(m.GetQuick(r, c), other.GetQuick(r, c))) } d = 0 } ch <- d }() } a = <-ch for j := 1; j < n; j++ { a = aggr(a, <-ch) } } else { a := f(m.GetQuick(0, 0), other.GetQuick(0, 0)) d := 1 // First cell already done. for r := 0; r < m.Rows(); r++ { for c := d; c < m.Columns(); c++ { a = aggr(a, f(m.GetQuick(r, c), other.GetQuick(r, c))) } d = 0 } } return a, nil }
// Applies a function to all cells with a given indexes and aggregates the // results. func (v *Vector) AggregateIndexed(aggr Float64Float64Func, f Float64Func, indexList []int) float64 { if v.Size() == 0 { return math.NaN() } size := len(indexList) var elem float64 var a float64 n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) c := make(chan float64, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { var b float64 = f(v.GetQuick(indexList[idx0])) var elem float64 for i := idx0 + 1; i < idx1; i++ { elem = v.GetQuick(indexList[i]) b = aggr(b, f(elem)) } c <- b }() } a = <-c for j := 1; j < n; j++ { a = aggr(a, <-c) } } else { a = f(v.GetQuick(indexList[0])) for i := 1; i < size; i++ { elem = v.GetQuick(indexList[i]) a = aggr(a, f(elem)) } } return a }
func (m *Matrix) AggregateProcedureSelection(aggr Float64Float64Func, f Float64Func, rowList, columnList []int) float64 { if m.Size() == 0 { return math.NaN() } size := len(rowList) var a float64 n := runtime.GOMAXPROCS(-1) if n > 1 && size > common.MatrixThreshold { n = common.Min(n, size) ch := make(chan float64, n) k := size / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = size } else { idx1 = idx0 + k } go func() { b := f(m.GetQuick(rowList[idx0], columnList[idx0])) for i := idx0 + 1; i < idx1; i++ { elem := m.GetQuick(rowList[i], columnList[i]) b = aggr(b, f(elem)) } ch <- b }() } a = <-ch for j := 1; j < n; j++ { a = aggr(a, <-ch) } } else { a = f(m.GetQuick(rowList[0], columnList[0])) for i := 1; i < len(rowList); i++ { elem := m.GetQuick(rowList[i], columnList[i]) a = aggr(a, f(elem)) } } return a }
// Applies a function to each corresponding cell of two matrices and // aggregates the results. Returns a value v such that // v==a(size()) where // a(i) == aggr( a(i-1), f(get(i), other.get(i)) ) and terminators // are a(1) == f(get(0), other.get(0)), a(0)==NaN. // // Example: // // x = 0 1 2 3 // y = 0 1 2 3 // // // Sum( x[i]*y[i] ) // x.aggregate(y, Plus, Mult) // --> 14 // // // Sum( (x[i]+y[i])^2 ) // x.aggregate(y, Plus, Chain(Square, Plus)) // --> 56 func (v *Vector) AggregateVector(other Vec, aggr, f Float64Float64Func) (float64, error) { err := v.checkSize(other) if err != nil { return math.NaN(), err } if v.Size() == 0 { return math.NaN(), nil } a := f(v.GetQuick(0), other.GetQuick(0)) n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) c := make(chan float64, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { b := f(v.GetQuick(idx0), other.GetQuick(idx0)) for i := idx0 + 1; i < idx1; i++ { a = aggr(a, f(v.GetQuick(i), other.GetQuick(i))) } c <- b }() } for j := 1; j < n; j++ { a = aggr(a, <-c) } } else { for i := 1; i < v.Size(); i++ { a = aggr(a, f(v.GetQuick(i), other.GetQuick(i))) } } return a, nil }
// Returns the number of cells having non-zero values; ignores tolerance. func (v *Vector) Cardinality() int { var cardinality int n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) c := make(chan int, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { card := 0 for i := idx0; i < idx1; i++ { if v.GetQuick(i) != 0.0 { card += 1 } } c <- card }() } cardinality = <-c for j := 1; j < n; j++ { cardinality += <-c } } else { cardinality = 0 for i := 0; i < v.Size(); i++ { if v.GetQuick(i) != 0.0 { cardinality += 1 } } } return cardinality }
// Swaps each element v[i] with other[i]. func (v *Vector) Swap(other Vec) error { err := v.checkSize(other) if err != nil { return err } n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { tmp := v.GetQuick(i) v.SetQuick(i, other.GetQuick(i)) other.SetQuick(i, tmp) } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for i := 0; i < v.Size(); i++ { tmp := v.GetQuick(i) v.SetQuick(i, other.GetQuick(i)) other.SetQuick(i, tmp) } } return nil }
// Assigns to each cell the result of a function taking as first argument // the current cell's value of this matrix, and as second argument the // current cell's value of "y". func (v *Vector) AssignVectorFunc(y Vec, f Float64Float64Func) (*Vector, error) { if y.Size() != v.Size() { return v, fmt.Errorf("Incompatible sizes: %d and %d", y.Size(), v.Size()) // return v, fmt.Errorf("Incompatible sizes: %s and %s", // v.StringShort(), NewFormatter().VectorShape(y)) } n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { v.SetQuick(i, f(v.GetQuick(i), y.GetQuick(i))) } done <- true }() } for j := 0; j < n; j++ { <-done } } else { // the general case x[i] = f(x[i],y[i]) for i := 0; i < v.Size(); i++ { v.SetQuick(i, f(v.GetQuick(i), y.GetQuick(i))) } } return v, nil }
// Assigns a value to all cells that satisfy a condition. func (v *Vector) AssignProcedure(cond Float64Procedure, value float64) *Vector { n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { elem := v.GetQuick(i) if cond(elem) { v.SetQuick(i, value) } } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for i := 0; i < v.Size(); i++ { elem := v.GetQuick(i) if cond(elem) { v.SetQuick(i, value) } } } return v }
// Replaces all cell values of the receiver with the values of another // matrix. Both matrices must have the same size. If both matrices share // the same cells (as is the case if they are views derived from the same // matrix) and intersect in an ambiguous way, then replaces as if // using an intermediate auxiliary deep copy of "other". func (v *Vector) AssignVector(other Vec) (*Vector, error) { if v.Size() != other.Size() { return v, fmt.Errorf("Incompatible sizes: %d and %d", v.Size(), other.Size()) // return v, fmt.Errorf("Incompatible sizes: %s and %s", // v.StringShort(), NewFormatter().VectorShape(other)) } n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) done := make(chan bool, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { for i := idx0; i < idx1; i++ { v.SetQuick(i, other.GetQuick(i)) } done <- true }() } for j := 0; j < n; j++ { <-done } } else { for i := 0; i < v.Size(); i++ { v.SetQuick(i, other.GetQuick(i)) } } return v, nil }
// Applies a function to each cell and aggregates the results. Returns a // value v such that v==a(size()) where // a(i) == aggr( a(i-1), f(get(i)) ) and terminators are // a(1) == f(get(0)), a(0)==NaN. // // Example: // // matrix = 0 1 2 3 // // // Sum( x[i]*x[i] ) // matrix.Aggregate(Plus, Square) // --> 14 func (v *Vector) Aggregate(aggr Float64Float64Func, f Float64Func) float64 { if v.Size() == 0 { return math.NaN() } a := f(v.GetQuick(0)) n := runtime.GOMAXPROCS(-1) if n > 1 && v.Size() > common.VectorThreshold { n = common.Min(n, v.Size()) c := make(chan float64, n) k := v.Size() / n var idx0, idx1 int for j := 0; j < n; j++ { idx0 = j * k if j == n-1 { idx1 = v.Size() } else { idx1 = idx0 + k } go func() { var b float64 for i := idx0 + 1; i < idx1; i++ { b = aggr(b, f(v.GetQuick(i))) } c <- b }() } for j := 1; j < n; j++ { a = aggr(a, <-c) } } else { for i := 1; i < v.Size(); i++ { a = aggr(a, f(v.GetQuick(i))) } } return a }