How to get a square matrix of mynum struct to inverse

#1

This is my toy program

import Base: ==, +, -, *, /, <

struct mynum <: Real
    value::Float64
end

mynum(x::mynum) = x
mynum(num::Real) = mynum(num)

Base.zero(::Type{mynum}) = mynum(0.0)
Base.one(::Type{mynum}) = mynum(1.0)
Base.iszero(x::mynum) = Base.iszero(x.value)
Base.isone(x::mynum) = Base.isone(x.value)
Base.convert(::Type{mynum}, num::Real) = mynum(num::Real)

+(x::mynum,y::mynum) = mynum(x.value+y.value)
-(x::mynum,y::mynum) = mynum(x.value-y.value)
*(x::mynum,y::mynum) = mynum(x.value*y.value)
/(x::mynum,y::mynum) = mynum(x.value/y.value)
==(x::mynum,y::mynum) = x.value == y.value
<(x::mynum,y::mynum) = x.value < y.value


a = mynum(3.4)
b = mynum(5.6)
c = a * b
println("c = ",c)

m_real = [ 1.0 2.0; 3.0 4.0]
println("m_real = ",m_real)
inv_m_real = inv(m_real)
println("inv_m_real = ",inv_m_real)

m = [ mynum(1.0) mynum(2.0); mynum(3.0) mynum(4.0) ]
println("m = ",m)
inv_m = inv(m)
println("invm = ",inv_m)

And this is the output

$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _  |  |
  | | |_| | | | (_| |  |  Version 1.0.3 (2018-12-18)
 _/ |\__ _|_|_|\__ _|  |  Official https://julialang.org/ release
|__/                   |

julia> include("mynum.jl")
c = mynum(19.04)
m_real = [1.0 2.0; 3.0 4.0]
inv_m_real = [-2.0 1.0; 1.5 -0.5]
m = mynum[mynum(1.0) mynum(2.0); mynum(3.0) mynum(4.0)]
ERROR: LoadError: StackOverflowError:
Stacktrace:
 [1] mynum(::Bool) at /Users/ssiew/juliascript/mynum.jl:8 (repeats 80000 times)
in expression starting at /Users/ssiew/juliascript/mynum.jl:36

Any idea how to get my square matrix to be inverse like the matrix of Float64?

Why is a type when used as a function given a boolean true return a number?
#2

The error message is pointing you to this line, which is causing a stack overflow. The right hand side of that function just ends up calling the function again, resulting in an infinite number of function calls. You can probably just delete this line entirely.

2 Likes
#3

I finally got my mynum to inverse by adding two STRANGE lines and one ORDINARY line

Line 1

# We need to define a strange Boolean function for OUR TYPE
mynum(x::Bool) = x ? mynum(1.0) : mynum(0.0)

Line 2

# For some reason we need this line below
Base.promote_rule(::Type{Int64}, ::Type{mynum}) = mynum

Line 3

# we also need to define this
-(x::mynum) = mynum( -1.0 * x.value)

So here it is the full source code

import Base: ==, +, -, *, /, <

struct mynum <: Real
    value::Float64
end

mynum(x::mynum) = x
mynum(num::Real) = mynum(  Base.parse(Float64,string(num))  )
# We need to define a strange Boolean function for OUR TYPE
mynum(x::Bool) = x ? mynum(1.0) : mynum(0.0)
Base.zero(::Type{mynum}) = mynum(0.0)
Base.one(::Type{mynum}) = mynum(1.0)
Base.iszero(x::mynum) = Base.iszero(x.value)
Base.isone(x::mynum) = Base.isone(x.value)
Base.convert(::Type{mynum}, num::Real) = mynum(num::Real)
# For some reason we need this line below
Base.promote_rule(::Type{Int64}, ::Type{mynum}) = mynum

+(x::mynum,y::mynum) = mynum(x.value+y.value)
-(x::mynum,y::mynum) = mynum(x.value-y.value)
*(x::mynum,y::mynum) = mynum(x.value*y.value)
/(x::mynum,y::mynum) = mynum(x.value/y.value)
# we also need to define this
-(x::mynum) = mynum( -1.0 * x.value)
==(x::mynum,y::mynum) = x.value == y.value
<(x::mynum,y::mynum) = x.value < y.value

a = mynum(3.4)
b = mynum(5.6)
c = a * b
println("c = ",c)

m_real = [ 1.0 2.0; 3.0 4.0]
println("m_real = ",m_real)
inv_m_real = inv(m_real)
println("inv_m_real = ",inv_m_real)

m = [ mynum(1.0) mynum(2.0); mynum(3.0) mynum(4.0) ]
println("m = ",m)
inv_m = inv(m)
println("invm = ",inv_m)

And here is the output

$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _  |  |
  | | |_| | | | (_| |  |  Version 1.0.3 (2018-12-18)
 _/ |\__ _|_|_|\__ _|  |  Official https://julialang.org/ release
|__/                   |

julia> include("mynum02.jl")
c = mynum(19.04)
m_real = [1.0 2.0; 3.0 4.0]
inv_m_real = [-2.0 1.0; 1.5 -0.5]
m = mynum[mynum(1.0) mynum(2.0); mynum(3.0) mynum(4.0)]
invm = mynum[mynum(-2.0) mynum(1.0); mynum(1.5) mynum(-0.5)]