tfiers / SpikeWorks.jl

Helping you build spiking neural network simulations in Julia
MIT License
1 stars 0 forks source link

real units (not fake) #1

Open tfiers opened 1 year ago

tfiers commented 1 year ago
julia> using Unitful

julia> @code_typed 3u"m"*8u"s"
CodeInfo(
1 โ”€ %1 = Base.getfield(x, :val)::Int64
โ”‚   %2 = Base.getfield(y, :val)::Int64
โ”‚   %3 = Base.mul_int(%1, %2)::Int64
โ”‚   %4 = %new(Quantity{Int64, ๐‹  ๐“ , Unitful.FreeUnits{(m, s), ๐‹  ๐“ , nothing}}, %3)::Quantity{Int64, ๐‹ ๐“, Unitful.FreeUnits{(m, s), ๐‹ ๐“, nothing}}
โ””โ”€โ”€      return %4
) => Quantity{Int64, ๐‹  ๐“ , Unitful.FreeUnits{(m, s), ๐‹  ๐“ , nothing}}

julia> @code_typed 3u"m"+8u"s"
CodeInfo(
1 โ”€ %1 = Unitful.DimensionError::Type{Unitful.DimensionError}
โ”‚   %2 = %new(%1, x, y)::Unitful.DimensionError
โ”‚        Unitful.throw(%2)::Union{}
โ””โ”€โ”€      unreachable
) => Union{}

very impressive

implementation:

# Addition / subtraction
for op in [:+, :-]
    @eval ($op)(x::AbstractQuantity{S,D,U}, y::AbstractQuantity{T,D,U}) where {S,T,D,U} =
        Quantity(($op)(x.val, y.val), U())

    @eval function ($op)(x::AbstractQuantity{S,D,SU}, y::AbstractQuantity{T,D,TU}) where {S,T,D,SU,TU}
        ($op)(promote(x,y)...)
    end

    @eval ($op)(x::AbstractQuantity, y::AbstractQuantity) = throw(DimensionError(x,y))
    @eval ($op)(x::AbstractQuantity) = Quantity(($op)(x.val), unit(x))
end
tfiers commented 1 year ago

Problem with the "switch between fake and real units": global constants / typeds

tfiers commented 1 year ago

The monster:

@code_typed 3u"mV"/8u"s"
CodeInfo(
1 โ”€ %1 = Base.getfield(x, :val)::Int64
โ”‚   %2 = Base.getfield(y, :val)::Int64
โ”‚   %3 = Base.sitofp(Float64, %1)::Float64
โ”‚   %4 = Base.sitofp(Float64, %2)::Float64
โ”‚   %5 = Base.div_float(%3, %4)::Float64
โ”‚   %6 = %new(Quantity{Float64, ๐‹ ^2 ๐Œ  ๐ˆ ^-1 ๐“ ^-4, Unitful.FreeUnits{(s^-1, mV), ๐‹ ^2 ๐Œ  ๐ˆ ^-1 ๐“ ^-4, nothing}}, %5)::Quantity{Float64, ๐‹^2 ๐Œ ๐ˆ^-1 ๐“^-4, Unitful.FreeUnits{(s^-1, mV), ๐‹^2 ๐Œ ๐ˆ^-1 ๐“^-4, nothing}}
โ””โ”€โ”€      return %6
) => Quantity{Float64, ๐‹ ^2 ๐Œ  ๐ˆ ^-1 ๐“ ^-4, Unitful.FreeUnits{(s^-1, mV), ๐‹ ^2 ๐Œ  ๐ˆ ^-1 ๐“ ^-4, nothing}}

Simplification of Unitful types, maybe:

Quantity{Float64, Unit{(mV, s^-1), L^2 M I^-1 T^-4}}
Quantity{Float64, Unit{(mV, sโปยน), Lยฒ M Iโปยน Tโปโด}}
Quantity{Float64, Unit{(mV/s), M Lยฒ / (Tโด I)}
Quantity{Float64, Unit{(mV /s), M Lยฒ /Tโด /I)}
Quantity{Float64, Unit{mV/s, Voltage/Time}}
Quantity{Float64, Unit{V, Tโปยน}}
Val{Float64, Unit{V, Tโปยน}}

(ofc, yes, "try not to display types; display values instead". ofc in practice that's no go, starting with just having a Vector of those. grrr. (#julia annoyance))

tfiers commented 1 year ago

what's those thangs in type

julia> q = 3m / 8s
0.375 m s^-1

julia> u = unit(q)
m s^-1

julia> T = typeof(u)
Unitful.FreeUnits{(m, s^-1), ๐‹  ๐“ ^-1, nothing}

julia> T.parameters[1][2]
s^-1

julia> typeof(T.parameters[1][2])
Unitful.Unit{:Second, ๐“ }

wat. where'd the -1 go.

julia> typeof(Unitful.s)
Unitful.FreeUnits{(s,), ๐“ , nothing}
tfiers commented 1 year ago

ah:

julia> x=T.parameters[1][2];
s^-1

julia> dump(x)
Unitful.Unit{:Second, ๐“ }
  tens: Int64 0
  power: Rational{Int64}
    num: Int64 -1
    den: Int64 1

julia> isbits(x)
true
tfiers commented 1 year ago

The above means that a sโปยน repr is for sure possible :)

tfiers commented 1 year ago

Problem with the "switch between fake and real units": global constants / typeds

Well, we'll just export two modules :) And then user just needs to switch the using stmt. (SpikeWorks.Units and SpikeWorks.FakeUnits, or sth)