Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbyrne committed Jul 15, 2023
1 parent 32590e5 commit 7f800c6
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 4 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# SuffixConversion
# SuffixConversion.jl

[![Build Status](https://github.com/simonbyrne/SuffixConversion.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/simonbyrne/SuffixConversion.jl/actions/workflows/CI.yml?query=branch%3Amain)

Defines suffix variables for making it easier to write generic code. The key interface is the `@suffix FT` macro which will define a variable prefixed with an underscore. When pre-multiplied by a number, this will perform conversion to the appropriate type. Specifically, it is designed to take advantage of Julia's [implicit multiplication of numerical literal coefficients](https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#man-numeric-literal-coefficients).

```
using SuffixConversion
function addhalf(x::FT) where {FT}
@suffix FT
return x + 0.5_FT
end
```

56 changes: 55 additions & 1 deletion src/SuffixConversion.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
module SuffixConversion

# Write your package code here.
export @suffix

"""
SuffixConverter{T}()
When used with suffix multiplication, it will convert the result to type `T`.
When used with `BigFloat`s, it will convert the convert via string conversion,
then parsing.
"""
struct SuffixConverter{T}
end

Base.:*(x::Number, ::SuffixConverter{FT}) where {FT} = convert(FT, x)
Base.:*(x::Number, ::SuffixConverter{BigFloat}) = BigFloat(string(x))

Base.Broadcast.broadcasted(::typeof(*), x::Number, s::SuffixConverter) = x * s


"""
@suffix T [= ....]
Defines a [`SuffixConverter`](@ref) for type `T` with the same name, prefixed by
an underscore. For convenience, it can also accept an expression which defines
`T` itself.`
# Examples
Using an already-defined type
```julia
function addhalf(x::FT) where {FT}
@suffix FT
return x + 0.5_FT
end
```
Defining the type inline
```julia
function addhalf(x)
@suffix FT = typeof(FT)
return x + 0.5_FT
end
```
"""
macro suffix(T::Symbol)
:($(esc(Symbol(:_, T))) = SuffixConverter{$(esc(T))}())
end

macro suffix(ex::Expr)
@assert ex.head == :(=) && ex.args[1] isa Symbol
quote
$(esc(ex))
$(esc(Symbol(:_, ex.args[1]))) = SuffixConverter{$(esc(ex.args[1]))}()
end
end

end
35 changes: 33 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
using SuffixConversion
using Test

@testset "SuffixConversion.jl" begin
# Write your tests here.
@testset "defined" begin
function addhalf(x::FT) where {FT}
@suffix FT
return x + 0.5_FT
end

@test addhalf(1.0) === 1.5
@test addhalf(1f0) === 1.5f0
@test addhalf(Float16(1)) === Float16(1.5)
end

@testset "inline definition" begin
function addhalf2(x)
@suffix FT = typeof(x)
return x + 0.5_FT
end

@test addhalf2(1.0) === 1.5
@test addhalf2(1f0) === 1.5f0
@test addhalf2(Float16(1)) === Float16(1.5)

end

@testset "broadcasting" begin
function addhalf_broadcast(X)
@suffix FT = eltype(X)
return @. X + 0.5_FT
end

@test eltype(addhalf_broadcast(Float64[1.0, 2.0])) == Float64
@test eltype(addhalf_broadcast(Float32[1.0, 2.0])) == Float32
@test eltype(addhalf_broadcast(Float16[1.0, 2.0])) == Float16
end

0 comments on commit 7f800c6

Please sign in to comment.