Linear Algebra with custom scalar product

Borrowing an example from the popular talk, let’s say I want to use LinearAlgebra.qr() , but with three-argument dot() introduced in Julia 1.4. So I need to define my own CustomVector that carries within it the middle argument A for three-argument dot product (and redefine reflector! because it assumes normal Euclidean scalar product). But arrays are not bit types, therefore CustomVector may not be parametrized by A. So it looks like the only way is to have a global A, common for all instances of CustomVector.

Is there some better way?

I’m not sure I entirely understand the usecase, but maybe something like this:

struct CustomVector{T, TA} <: AbstractVector{T}
    data::Vector{T}
    A::TA
end

(You would also want to implement the AbstractArray interface if you subtype AbstractVector: Interfaces · The Julia Language).

You don’t need to put A as a type parameter to use it, e.g.

my_dot(v::CustomVector, u::AbstractVector) = dot(v.data, v.A, u)

There should be some way to prevent multiplication of instances with different A

1 Like

I thought I remembered someone (@Mason?) showing recently how to locally redefine a function inside a let block. Maybe you could locally redefine dot?

You could just have a runtime check and throw an error if v.A !== u.A (!== checks object identity).

No, that’s the same as defining a local variable that shadows a global variable. A local definition of dot would not be visible inside the qr function.

2 Likes

You probably mean ===, because == is doing elementwise comparison of the arrays.

No, !== is the negation of ===, the negation of == is !=.

1 Like

I stand corrected. It would probably be necessary to specialise deepcopy() to avoid dupicating A.

Another possible implementation would parameterize CustomVector with pointer to A. It would then be necessary to wrap the computation in @GC.preserve A. Not sure it would’ve any advantages over comparing references to A.