Gonum генерирует плохую область паники при использовании встроенной структуры

Я использую gonum для выполнения нескольких расчетов по линейной алгебре. После расширения оригинала mat.VecDense struct Я получаю "плохую область: идентичная" паника при применении метода к себе. Эта ошибка не возникает, когда я использую оригинальную настройку gonum.

Вот моя реализация:

type Vector struct {
    mat.VecDense
}
func NewVector(n int, data []float64) *Vector {
    return &Vector{*mat.NewVecDense(n, data)}
}

Я тестирую его, используя следующий фрагмент:

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\n", &u, u)
    fmt.Printf("[V - NewVecDense]\tADDRESS: %v, VALUE: %v\n", &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\n", &x, x)
    fmt.Printf("[Y - NewVector]\tADDRESS: %v, VALUE: %v\n", &y, y)
    x.AddVec(x, y)
    fmt.Println(x)
}

В то время как первое дополнение выполняется нормально, второе завершается ошибкой:

[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 метод, реализованный gonum:

func (v *VecDense) AddVec(a, b Vector)

Почему это происходит, и как правильно это осуществить?


Редактировать:

Благодаря @Himanshu мне удалось решить проблему.

Я создал сквозные методы для каждого используемого мной метода, передавая правильный уровень структуры через:

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)
}

Кроме того - я не уверен, что это правильный подход или нет - я также изменил тип возвращаемого значения для NewVector от указателя к значению, так как он содержит указатель на mat.VecDense тем не мение. Обратите внимание, что *mat.VecDense удовлетворяет Vector интерфейс от gonum, поэтому передача этого внутреннего поля в методы работала нормально, как показано в примере выше.

1 ответ

Решение

На Голанге это описано для продвигаемых методов как

Продвигаемые поля действуют как обычные поля структуры, за исключением того, что они не могут использоваться в качестве имен полей в составных литералах структуры.

При заданном типе структуры S и определенном типе T продвигаемые методы включаются в набор методов структуры следующим образом:

  • Если S содержит встроенное поле T, наборы методов S и *S включают в себя повышенные методы с получателем T. Набор методов *S также включает повышенные методы с получателем *T.
  • Если S содержит встроенное поле *T, наборы методов S и *S оба включают повышенные методы с приемником T или *T.

Проблема в том, что вы передаете аргументы типа указателя AddVec функция. Но вы используете поля типа указателя во втором случае.

func (v *VecDense) AddVec(a, b Vector)

Еще одна вещь, на которую следует обратить внимание: AddVec имеет аргументы типа значения Vector структура, но вы передаете указатель на Vector поля как

x, y := NewVector(3, []float64{1, 2, 3}), NewVector(3, []float64{4, 5, 6}) 

В приведенном выше коде x,y Тип указателя возвращается из NewVector

x.AddVec(x, y)

Проблема в том, что указатели сравниваются при обнаружении теней. Это ошибка ИМО. Я только что подал https://github.com/gonum/gonum/issues/945

Другие вопросы по тегам