Skip to content

inverse of matrices over arbitrary fields stopped working in julia1.5.0-beta1 #734

@jmichel7

Description

@jmichel7

I haved used julia since 0.6, and at all times matrix inverse worked for fields I have defined (finite fields, cyclotomic fields, rational fractions...). It stooped working in 1.5.9-beta1

Here is a MWE where I define a matrix over a finite prime field

   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.4.2 (2020-05-23)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> struct Mod{p} <: Number
          val::Int
          function Mod{p}(a::Integer) where {p}
                  new(mod(a,p))
          end
       end

julia> Base.zero(::Type{Mod{p}}) where p = Mod{p}(0)

julia> Base.:+(x::Mod{p}, y::Mod{p}) where p = Mod{p}(x.val+y.val)

julia> Base.:*(x::Mod{p}, y::Mod{p}) where p = Mod{p}(x.val*y.val)

julia> Base.:-(x::Mod{p}) where {p} = Mod{p}(-x.val)

julia> Base.:-(x::Mod{p}, y::Mod{p}) where p =x+(-y)

julia> Base.inv(x::Mod{p}) where p = Mod{p}(invmod(x.val,p))

julia> Base.:/(x::Mod{p}, y::Mod{p}) where p = x * inv(y)

julia> Base.isless(x::Mod{p}, y::Mod{p}) where p=x.val<y.val

julia> Base.abs(x::Mod)=x

julia> Base.conj(x::Mod)=x

julia> m=Mod{19}.([1 2 3;3 2 1;1 0 0])
3×3 Array{Mod{19},2}:
 Mod{19}(1)  Mod{19}(2)  Mod{19}(3)
 Mod{19}(3)  Mod{19}(2)  Mod{19}(1)
 Mod{19}(1)  Mod{19}(0)  Mod{19}(0)

julia> inv(m)*m
3×3 Array{Mod{19},2}:
 Mod{19}(1)  Mod{19}(0)  Mod{19}(0)
 Mod{19}(0)  Mod{19}(1)  Mod{19}(0)
 Mod{19}(0)  Mod{19}(0)  Mod{19}(1)

This stopped working in 1.5.0-beta1

julia> inv(m)
ERROR: MethodError: no method matching AbstractFloat(::Mod{19})
Closest candidates are:
  (::Type{T})(::T) where T<:Number at boot.jl:716
  AbstractFloat(::Bool) at float.jl:258
  AbstractFloat(::Int8) at float.jl:259
  ...
Stacktrace:
 [1] float(::Mod{19}) at ./float.jl:277
 [2] norm at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/generic.jl:648 [inlined] (repeats 2 times)
 [3] #generic_lufact!#143 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lu.jl:143 [inlined]
 [4] #lu!#142 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lu.jl:130 [inlined]
 [5] #lu#144 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lu.jl:273 [inlined]
 [6] lu at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/lu.jl:272 [inlined] (repeats 2 times)
 [7] inv(::Array{Mod{19},2}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/dense.jl:809
 [8] top-level scope at REPL[14]:1

But the code for inverting matrices over an arbitrary field must still be somewhere in the library since inverting matrices of rationals still work. How do I use the code for inverting matrices over arbitrary fields for my own types?

Metadata

Metadata

Assignees

Labels

regressionRegression in behavior compared to a previous version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions