Skip to content

10x15 matrix, snf crashes over Int64 because of overflow; it gives incorrect result over Int128. #7

@lampretl

Description

@lampretl

The following code

using SmithNormalForm
X = [ 8   0  -18  -2    0   65   9  0   0  0  0   6   9  0   22;
     -4   0    0   1    0   -1   0  0   0  0  0   6   0  0   -4;
    -60   6  -54   6   13  -12  -3  0   0  0  0  42   0  0  -16;
     34  -7   71   2   -6  -23  -6  0  -1  0  0  -3  -4  0   -9;
      0   0    0   0    0    0  -1  0   0  0  0   0   0  0    0;
      0   0   -2   0    0    7   0  0   0  0  0   2   1  0    2;
      0   0    0   0    0    0   0  0   0  0  0   0   0  0    1;
     -6   1   -9   0    2   -1   0  0   0  0  0   1   0  0    0;
     28  -9   97   7  -18  -54  -1  0   0  0  0  17  -8  0  -48;
     -8   4  -50  -4    8   49  -9  0   0  0  0  -6   7  0   31 ];   
U,V,D = SmithNormalForm.snf(Int64.(X));

produces

ERROR: DivideError: integer division error
Stacktrace:
 [1] div
   @ ./int.jl:295 [inlined]
 [2] bezout
   @ ~/.julia/packages/SmithNormalForm/eLg8H/src/bezout.jl:12 [inlined]
 [3] colpivot(V::Matrix{Int64}, Vinv::Matrix{Int64}, D::Matrix{Int64}, i::Int64, j::Int64; inverse::Bool)
   @ SmithNormalForm ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:108
 [4] colpivot
   @ ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:98 [inlined]
 [5] smithpivot(U::Matrix{Int64}, Uinv::Matrix{Int64}, V::Matrix{Int64}, Vinv::Matrix{Int64}, D::Matrix{Int64}, i::Int64, j::Int64; inverse::Bool)
   @ SmithNormalForm ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:128
 [6] smithpivot
   @ ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:118 [inlined]
 [7] snf(M::Matrix{Int64}; inverse::Bool)
   @ SmithNormalForm ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:207
 [8] snf(M::Matrix{Int64})
   @ SmithNormalForm ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:173
 [9] top-level scope
   @ REPL[62]:1

Running U,V,D = SmithNormalForm.snf(Int128.(X)); X == U*D*V finishes successfully and returns true, but this is valid only modulo 2^128, because big.(X) == big.(U)*big.(D)*big.(V) returns false.

Running U,V,D = SmithNormalForm.snf(BigInt.(X)) returns

ERROR: MethodError: no method matching typemax(::Type{BigInt})

Closest candidates are:
  typemax(::Union{Dates.DateTime, Type{Dates.DateTime}})
   @ Dates ~/julia-1.9.2/share/julia/stdlib/v1.9/Dates/src/types.jl:444
  typemax(::Union{Dates.Date, Type{Dates.Date}})
   @ Dates ~/julia-1.9.2/share/julia/stdlib/v1.9/Dates/src/types.jl:446
  typemax(::Union{Dates.Time, Type{Dates.Time}})
   @ Dates ~/julia-1.9.2/share/julia/stdlib/v1.9/Dates/src/types.jl:448
  ...

Stacktrace:
 [1] snf(M::Matrix{BigInt}; inverse::Bool)
   @ SmithNormalForm ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:189
 [2] snf(M::Matrix{BigInt})
   @ SmithNormalForm ~/.julia/packages/SmithNormalForm/eLg8H/src/snf.jl:173
 [3] top-level scope
   @ REPL[18]:1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions