Angle package

Hi community!

Is it a radian? Is it a degree? Who cares! With Angles.jl you’ll never again need to worry about using sin or sind.

I built the package we discussed in the previous discussion about a native angle type. The package is not registered yet because I’m hoping for a major breakthrough in how an Angle could automatically inherit all of the functionalities a subtype of Number has (see some details about that in this topic).

Please feel free to contribute, file issues, PR, etc. I’d appreciate any input you might have.

Cheers!

Yakir

2 Likes

Very convenient! Thanks!

1 Like

You’re replacing methods defined in Base (namely those of inverse trigonometric functions with Number input), I think this configures as type piracy.

Oh… how? I didn’t (over)write a asin function, I made a new arcsin function. Not sure I understand how that is type piracy. Could you explain?

Oh, sorry, didn’t notice the names were different from those in Base. However, the point of the package is to avoid confusion between sin/sind functions (and that’s fine), but now you’re introducing new inverse functions that does the practically same as functions in Base. Isn’t this a contradiction?

Yea, you’re right, but hell if I know how to make asin spit a (say) Radian without committing type piracy. Let me know if you know how (seriously).

Probably I wouldn’t have defined methods for inverse functions :slight_smile: Or, maybe, extend base methods with an extra argument specifying the return type, that relies, for example, on asin/asind?

asin(-0.5, Radian)
asin(sqrt(3)/2, Degree)

“The first argument can be omitted to get the default” is a pretty standard pattern too, eg

asin(Radian, 0.5)

I like that a lot! Here is the method with the two-argument version:

julia> using Angles

julia> import Base.asin

julia> asin(::Type{T}, x::Number) where {T <: Angle} = T(Radian(asin(x)))
asin (generic function with 11 methods)

julia> asin(Degree, 0.5)
Angles.Degree{Float64}(30.000000000000004)

But how would you define the method for when the first argument is omitted without committing type piracy on the normal version of asin?

I wouldn’t. That’s the point — Base.asin is defined, the fallback is radians, no existing code breaks.

Sorry, I thought you meant there would be a way to call asin(x) and get Radian back. But the only two options I have is either having a new function with just one argument (e.g. arcsin(x)), or the good-old asin with two arguments (i.e. asin(::Type{T}, x)). Correct?

I was just suggesting that extending Base.asin in with an extra parameter may be a good design choice.

I understand and agree. Doing it.

Ordinarily, I would expect that Angle should be a subtype of Number, in the same way that Unitful.Quantity is. Also, I’m not sure why you aren’t building this package on top of Unitful, which implements a lot of infrastructure to handle units and already has a degree type.

Agreed, I changed Angle to be a subtype of Number.

My motivations to not building this on top of Unitful are:

  • This is a learning process for me.
  • Unitful is big, complete, and works really well in context of other units and dimensions. I love it! But this Angles package is really small, doesn’t do much more than keeping the trig functions in check, and is more of a test to see if people would like to have an innate Angle type in Julia.
  • Are there other entities that are in Unitful and should/could get refractured into their own little packages? Are there things in Julia that should be in Unitful? Hard to answer, but arguable for sure. I feel that Angles falls into one of these grey zones: angles are more widely used than say volumes, and could benefit from their own smaller package.

Unless you want to give meaning to a complex angle, the angle should be a real quantity, so Angle should be better a subtype of Real, rather than Number. You’d also replace all occurrences of Number with Real in the code.

Perfectly meaningful…what do you think asin(1.2+0im) is?

The extension to complex plane of a well defined mathematical function. I mean, is there a physical meaning of “1.2 + 3.4im radians/degrees”? deg2rad and rad2deg aren’t defined for complex input in Julia (for the record, they should be in Matlab). The package seems more oriented to handle conversion between physical angles with different units.

Or I could just keep it as a subtype of Number, extending the functionality of the package to include angles with imaginary numbers and not losing any of its performance (I think…).

Sorry, I don’t get what you mean.

My point is that, as far as I know, there is no such thing like “complex angle”. There are complex numbers to which trigonometric functions can be applied, but I couldn’t find an interpretation of these numbers as geometrical or physical angles. I thought about solid angles, that are two-dimensional angles, but it doesn’t seem that complex numbers are used to represent in any way solid angles.

1 Like