I am using gonum to perform a few linear algebra calculations. After extending the original mat.VecDense
struct I am getting a "bad region: identical" panic when applying a method on itself. This error does not occur when I am using the original setup gonum provides.
Here is my implementation:
type Vector struct {
mat.VecDense
}
func NewVector(n int, data []float64) *Vector {
return &Vector{*mat.NewVecDense(n, data)}
}
I am testing it using the following snippet:
func main() {
u, v := mat.NewVecDense(3, []float64{1, 2, 3}), mat.NewVecDense(3, []float64{4, 5, 6})
fmt.Printf("[U - NewVecDense]\tADDRESS: %v, VALUE: %v
", &u, u)
fmt.Printf("[V - NewVecDense]\tADDRESS: %v, VALUE: %v
", &v, v)
u.AddVec(u, v)
fmt.Println("-------------------------")
x, y := NewVector(3, []float64{1, 2, 3}), NewVector(3, []float64{4, 5, 6})
fmt.Printf("[X - NewVector]\tADDRESS: %v, VALUE: %v
", &x, x)
fmt.Printf("[Y - NewVector]\tADDRESS: %v, VALUE: %v
", &y, y)
x.AddVec(x, y)
fmt.Println(x)
}
While the first addition executes fine, the second fails:
[U - NewVecDense] ADDRESS: 0xc42000c028, VALUE: &{{[1 2 3] 1} 3}
[V - NewVecDense] ADDRESS: 0xc42000c030, VALUE: &{{[4 5 6] 1} 3}
-------------------------
[X - NewVector] ADDRESS: 0xc42000c040, VALUE: &{{{[1 2 3] 1} 3}}
[Y - NewVector] ADDRESS: 0xc42000c048, VALUE: &{{{[4 5 6] 1} 3}}
panic: mat: bad region: identical
AddVec
is a method implemented by gonum:
func (v *VecDense) AddVec(a, b Vector)
Why is this happening, hand what is the right way of implementing this?
Edit:
Thanks to @Himanshu I managed to solve the problem.
I created pass-through methods for each method I am using, passing the right level of the struct through:
type Vector struct {
*mat.VecDense
}
func NewVector(n int, data []float64) Vector {
return Vector{mat.NewVecDense(n, data)}
}
func (v *Vector) AddVec(a, b Vector) {
v.VecDense.AddVec(a.VecDense, b.VecDense)
}
func (v *Vector) SubVec(a, b Vector) {
v.VecDense.SubVec(a.VecDense, b.VecDense)
}
func (v *Vector) ScaleVec(alpha float64, a Vector) {
v.VecDense.ScaleVec(alpha, a.VecDense)
}
func (v *Vector) AddScaledVec(a Vector, alpha float64, b Vector) {
v.VecDense.AddScaledVec(a.VecDense, alpha, b.VecDense)
}
In addition - I am not sure if this is the right approach or not - I have also changed the return type for NewVector
from pointer to value, since it holds a pointer to the mat.VecDense
anyway. Note that *mat.VecDense
satisfies the Vector
interface from gonum, so passing this internal field on to the methods worked fine, as the example above shows.