Functions in degrees

1,194 views
Skip to first unread message

Hans W Borchers

unread,
Feb 4, 2014, 11:57:16 AM2/4/14
to julia...@googlegroups.com
I was astonished to see the following functions in the Julia Standard Library,
functions that accept (or return) degrees instead of radians:

    sind    asind   secd    asecd
    cosd    acosd   cscd    acscd
    tand    atand   cotd    acotd

I didn't find these function names in any other technical computing system.
Each of these functions can easily be reconstructed by the user applying the
functions degrees2radians() and radians2degrees().

I feel these function names clutter the namespace of Julia Base without being
of any real value. Therefore, I would like to vote for deprecating use of these
functions in the next version of Julia.

Hans Werner

Johan Sigfrids

unread,
Feb 4, 2014, 12:09:45 PM2/4/14
to julia...@googlegroups.com
I agree with this. It seems like a lot of extra namespace usage. Besides, if degrees2radians() is too long you always could define a constant and use that:

const DEGREE = pi/180
sin
(90DEGREE)

Stuart Brorson

unread,
Feb 4, 2014, 12:44:51 PM2/4/14
to julia...@googlegroups.com
These functions are included in Matlab as convenience functions. They
do get used frequently by folks working with real-world measurements.
It is true that one can always do rad = (x/180)*pi, but this
introduces the possibility of one ULP error in the calling arg. Not
big, admittedly, but try doing sind(180) vs. sin(pi) and see what the
results are.

In any event, keeping them around as convenience functions is useful
for folks coming from (or porting code from) at Matlab background.

Just my opinion.

Stuart

Kevin Squire

unread,
Feb 4, 2014, 12:49:32 PM2/4/14
to julia...@googlegroups.com
Seems like a reasonable suggestion to me, and it's certainly good to bring it up for discussion.

It doesn't have to be immediate, but if there is further consensus, it would be good to file an issue, or this is likely to get lost.

Cheers,

   Kevin 

Hans W Borchers

unread,
Feb 4, 2014, 12:54:01 PM2/4/14
to julia...@googlegroups.com
You are right. I have done real-world projects with Matlab, and I am giving
lectures on Matlab, but I have never seen or used these functions. I guess
removing them now they are here will not be reasonable.

I fear, some of my students will be glad to hear about these functions.

Kevin Squire

unread,
Feb 4, 2014, 12:54:06 PM2/4/14
to julia...@googlegroups.com
introduces the possibility of one ULP error in the calling arg.  Not
big, admittedly, but try doing sind(180) vs. sin(pi) and see what the
results are.

Slightly off topic, but I just wanted to note that are also sinpi and cospi functions (although no other related functions) which give more accurate results for multiples of pi.

julia> sin(pi)
1.2246467991473532e-16

julia> sinpi(1)
0

Cheers,

   Kevin

Jacob Quinn

unread,
Feb 4, 2014, 12:55:13 PM2/4/14
to julia...@googlegroups.com
As someone who doesn't have to work with the functions very often or deal with degrees/radians conversions, I actually have found it convenient to have the sind functions. It saves me time from having to remember what the conversion is or make my code uglier littered with degrees2radians() conversions, for example, in the following haversine distance calc.

haversine(lat1,lon1,lat2,lon2) = 12745.6 * asin(sqrt(sind((lat2-lat1)/2)^2 + cosd(lat1) * cosd(lat2) * sind((lon2 - lon1)/2)^2))

Hans W Borchers

unread,
Feb 5, 2014, 3:31:42 AM2/5/14
to julia...@googlegroups.com, quinn....@gmail.com
You could easily add these two lines of function definitions to your code.

    sind(x) = sin(degrees2radians(x))
    cosd(x) = cos(degrees2radians(x))

and your haversine function stands as is, not littered with conversions.

Ivar Nesje

unread,
Feb 5, 2014, 3:42:59 AM2/5/14
to julia...@googlegroups.com, quinn....@gmail.com
Hans W Borchers: Your definition is not equivalent.

julia> sin(pi)
1.2246467991473532e-16 

julia> sind(180)
0.0

julia> sinpi(1)
0

julia> sin(big(pi))
1.096917440979352076742130626395698021050758236508687951179005716992142688513354e-77 with 256 bits of precision

The answer for sin(pi) is somewhat correct, because float(pi) is not the π you know from mathematics. It is the closest representable IEEE 754 floating point number.

Ivar

Simon Byrne

unread,
Feb 5, 2014, 5:18:38 AM2/5/14
to julia...@googlegroups.com, quinn....@gmail.com
As I understand it, the original reason for the degree functions was for matlab compatibility, but they were later modified (and pi-multiple functions sinpi/cospi introduced) so as to be more accurate outside the the interval [-pi/2,pi/2], as Ivar points out. Note that we haven't improved on the naive approach on values within this interval, e.g. 

julia> sind(30)

0.49999999999999994

Matlab gets this wrong as well, but lies about it:

>> sind(30)

ans =

    0.5000

>> sind(30)-0.5

ans =

  -5.5511e-17

As to their use, I don't know about the degree functions, but the sinpi/cospi functions are actually used internally in a couple of places, in the definition of sinc and a couple of the bessel functions.

However that doesn't mean the interface couldn't be improved. One possible approach I've been thinking about is defining "degree" and "pi-multiple" types

immutable Degree <: Real
  deg::Float64
end

immutable PiMultiple <: Real
  mult::Float64
end

In this way we could leverage multiple dispatch: i.e. sind(x) becomes sin(Degree(x)) and sinpi(x) becomes sin(PiMultiple(x)). Of course, since julia doesn't (yet) provide a way to dispatch on return types, there's not an easy way to define the corresponding inverse functions, but this is typically less of an issue in terms of numerical error due to the constrained output range (the exception being atan2, where something like this could be very useful.

Simon

Johan Sigfrids

unread,
Feb 5, 2014, 7:48:38 AM2/5/14
to julia...@googlegroups.com, quinn....@gmail.com
Oh, you beat me to it. I was just about to say that using a Degree type and dispatching on it would be a lot more Julian. In fact, I had this great idea on how to use the degree sign to construct degrees:

module DegreeModule

export Degree, DegreeSign, °

immutable
Degree{T<:Number} <:Number
    d
::T
end

immutable
DegreeSign
    filler
::Bool
end

const ° = DegreeSign(true)

*(num::Number, s::DegreeSign) = Degree(num)

Base.sin(d::Degree) = sinpi(d.d/180)

end



Then it would Just Work™:

using DegreeModule

Degree(125)       # ==> Degree{Int64}(125)

130°              # ==> Degree{Int64}(130)

sin
(180°)         # ==> 0.0

I'm not familiar enough with Julia to know if that is the best way to construct the degree sign functionality, but I thought it was kinda elegant.

Stefan Karpinski

unread,
Feb 5, 2014, 10:38:12 AM2/5/14
to Julia Users, Jacob Quinn
I rather like the Degree type idea. Radians are unitless so they don't need a type – i.e. PiMultiple is just the default for all trig functions. You could, however, also have things angular units like Turns.

Stefan Karpinski

unread,
Feb 5, 2014, 10:40:41 AM2/5/14
to Julia Users, Jacob Quinn
What's particularly nice about having Degree and Turn and such is that you can apply the same exact generic code to any mixture of angular measurements in different units and still get the correct answers. I'm a little concerned about the need to redefine so many basic operations for angular quantities, but maybe that's ok.

Ivar Nesje

unread,
Feb 5, 2014, 10:49:26 AM2/5/14
to julia...@googlegroups.com, Jacob Quinn
I think the Degree types will be too hard to discover, so it will not be used enough that it is worth the extra work with all functions you might want to call on that number. This belongs more in a unit package like https://github.com/loladiro/SIUnits.jl , where some missing functions might be expected.

Ivar

ma.laf...@gmail.com

unread,
Mar 1, 2015, 5:57:37 AM3/1/15
to julia...@googlegroups.com, quinn....@gmail.com
I like that idea as well, but I would argue that radians should indeed have their own type *despite* being unitless.  Julia's multi-dispatch system would make calling angle-dependent functions safer, and promote the use of shorter names.

As an added benefit, unit conversion could be easily achieved on a function-by-function basis (I feel blanketed auto-promotion for units might be dangerous).

I built a very simple mockup to try it out.  I used Inch <-> Meter conversion as an example (hoping it might capture a broader audience), but I think it would deal perfectly with this very issue:
https://github.com/ma-laforge/testcases/tree/master/units_test (see units_test.jl)

I do not fully appreciate what would be needed to retrofit Julia's basic operations, but I would guess you could comment on that.

Simon Danisch

unread,
Mar 1, 2015, 8:00:01 AM3/1/15
to julia...@googlegroups.com
Seems like another case for this discussion:

Stuart Brorson

unread,
Mar 1, 2015, 12:09:17 PM3/1/15
to julia...@googlegroups.com
> Am Dienstag, 4. Februar 2014 17:57:16 UTC+1 schrieb Hans W Borchers:
>>
>> I was astonished to see the following functions in the Julia Standard
>> Library,
>> functions that accept (or return) degrees instead of radians:
>>
>> sind asind secd asecd
>> cosd acosd cscd acscd
>> tand atand cotd acotd
>>
>> I didn't find these function names in any other technical computing system.

Actually, these are present in Matlab. Two examples:

http://www.mathworks.com/help/matlab/ref/sind.html
http://www.mathworks.com/help/matlab/ref/acotd.html

Many people come to Julia from Matlab, and may expect to find those
functions present. One man's namespace clutter is another man's
convenience function.

I'm not arguing for or against inclusion of these fcns in Julia, but I
am pointing out that they have precedent in other, popular computing
systems.

Stuart

Steven G. Johnson

unread,
Mar 1, 2015, 5:00:24 PM3/1/15
to julia...@googlegroups.com
The errors in sin and cos can be much larger than 1ulp for sin or cos of large phase angles (>> 360) in degrees, because pi is not exactly representable in fp while 180 is.

MA Laforge

unread,
Mar 1, 2015, 11:46:49 PM3/1/15
to julia...@googlegroups.com
Good to know.  The proposed method does not appear to have issues dealing with this.  Multi-dispatch can still pick up the appropriate trig() function.  See snippet I just added for angles:
https://github.com/ma-laforge/testcases/blob/master/units_test/units_test_angles.jl

As the code shows: Functions are easy to add once types are defined:
Base.sin(x::Radians) = sin(val(x))
Base.sin(x::Degrees) = sind(val(x))
Base.sin(x::Angle) = sin(Radians(x))

Typed angles should help maintain a compact namespace (even if we include "Revolutions" as an angle).

As for Stuart's comment:
Maybe Julia modules should include a Matlab compatibility submodules to reduce clutter:
module Trigonometry #Probably excessive
...
   
module MatlabCompatibility
   
...
   
end
end

module Algebra #Probably excessive
...
   
module MatlabCompatibility
   
...
   
end
end

using Trigonometry
using Algebra
using MatlabCompatibility

MA Laforge

unread,
Mar 1, 2015, 11:53:00 PM3/1/15
to julia...@googlegroups.com
Oops. Please disregard comment on Matlab compatibility.
I am almost certain Julia cannot support it in this way.

Yuuki Soho

unread,
Mar 2, 2015, 8:14:27 AM3/2/15
to julia...@googlegroups.com
One advantage of having a Radian type would be to have circular statistics built-in, mainly mean, var, std or cor. Other languages usually have special functions or packages for that (circmean).

Gustavo Goretkin

unread,
Mar 2, 2015, 12:46:55 PM3/2/15
to julia...@googlegroups.com, quinn....@gmail.com
Radian has dimensions of [(arc) length] / [(radius) length], so it's dimensionless because the two dimensions of [length] cancel out.
Turn has dimensions of [(arc) length] / [(circumference) length], so it's just as dimensionless as Radian, right?

https://en.wikipedia.org/wiki/Dimensionless_quantity#Properties seems to make a distinction between "dimension(less)" and "unit(less)". I think it could make sense to have types to distinguish among different dimensionless quantities that have different units.

Kevin Squire

unread,
Mar 2, 2015, 1:03:44 PM3/2/15
to julia...@googlegroups.com
By dimensionless, I assume you mean unitless.

Just because a value unitless doesn't mean it can't have a type. In this case, the type is more like a tag that indicated some information about the quantity useful for dispatch. While "type" can indicate "unit", it doesn't have to. 

Cheers,
   Kevin

Kevin Squire

unread,
Mar 2, 2015, 1:05:00 PM3/2/15
to julia...@googlegroups.com
(Sorry, I missed the bottom of your message where you distinguish "dimensionless" and "unitless".)


On Monday, March 2, 2015, Gustavo Goretkin <gustavo....@gmail.com> wrote:

ggggg

unread,
Mar 2, 2015, 6:41:33 PM3/2/15
to julia...@googlegroups.com
It's not really relevant to Julia, but there are many who would argue that there should be a base unit for angles. My personal favorite consequence of this choice is that Torque and Energy appear to have the same units.

For example:

Issue 10: the SI needs a base unit of angle ‘Angle’ is as tangible a geometric quantity as length, but the SI does not have a corresponding base quantity or unit for angle. The radian is a derived unit in the SI, defined from the identity s = r · θ (in which r is the radius of a circle and s is the length of the arc subtended by the angle θ ). From this definition, the radian has the unit m/m, and is said to be a dimensionless derived unit [34]. This definition has several undesirable consequences for rotational quantities, for example the SI unit for a rate of rotation is a ‘per second’, without any reference to the angle through which rotation takes place, or its unit [50]. There is ongoing confusion in textbooks about when radian units should be inserted or deleted in quantity expressions [51, 52]. 

MA Laforge

unread,
Mar 2, 2015, 7:57:10 PM3/2/15
to julia...@googlegroups.com
:+1
That's a good point.  I have myself experienced problems calculating mean when periodicity is not taken into account.

As for dimensionless quantities: I see no issue assigning a type to them (other than a potential re-design of the Julia libraries... gross). In fact, I expect alot of convenience with *typical* use cases.

The real question is how much programming overhead is required to use these types (assuming the compiler does the grunt work reducing the *performance* overhead).

For example, you can easily/quickly obtain "typeless" values with "val":
abstract Unit
val
(x::Unit) = x.v
abstract Angle <: Unit
immutable type
Radians{T<:Number} <: Angle
   v
::T
end
unitlessVal
= val(Radians(pi))

(See: https://github.com/ma-laforge/testcases/blob/master/units_test/units_test_angles.jl)

Steven G. Johnson

unread,
Mar 3, 2015, 2:40:31 PM3/3/15
to julia...@googlegroups.com


On Monday, March 2, 2015 at 7:57:10 PM UTC-5, MA Laforge wrote:
The real question is how much programming overhead is required to use these types (assuming the compiler does the grunt work reducing the *performance* overhead)
 
No, the real question is whether the benefit of using special types for radians vs. degrees would outweigh the costs of retraining every single user from every single previous mainstream programming language.   To me, there is no contest — doing angles differently from every other programming language would impose enormous costs in teaching, documentation, and support (imagine the never-ending flood of mailing-list questions) that would completely overwhelm the benefit of eliminating a "d" suffix on a few functions and automating a few angle conversions.

Stefan Karpinski

unread,
Mar 3, 2015, 2:52:06 PM3/3/15
to Julia Users
Then again, using type wrappers for this – bare numbers are Radians while an immutable Degree wrapper could wrap values in degrees – would eliminate a large class of common programming errors when working with angles.

Steven G. Johnson

unread,
Mar 3, 2015, 3:04:04 PM3/3/15
to julia...@googlegroups.com


On Tuesday, March 3, 2015 at 2:52:06 PM UTC-5, Stefan Karpinski wrote:
Then again, using type wrappers for this – bare numbers are Radians while an immutable Degree wrapper could wrap values in degrees – would eliminate a large class of common programming errors when working with angles.

I'm not sure what errors you think it will prevent.    It won't prevent a programmer from passing am angle in degrees to a function expecting radians, unless the programmer remembers to use the Degree wrapper — but in that case why wouldn't she remember to do the conversion?
 
The only way to prevent that kind of error would be to not allow bare numbers at all in trig functions, even for radians.  And the cost of that radical a departure from existing practice is unlikely to be worth it.

Stefan Karpinski

unread,
Mar 3, 2015, 3:07:10 PM3/3/15
to Julia Users
That's a fair point. You'd have to require the type wrapper to make it actually effective.

Stuart Brorson

unread,
Mar 3, 2015, 3:57:28 PM3/3/15
to julia...@googlegroups.com
On Tue, 3 Mar 2015, Steven G. Johnson wrote:
> On Monday, March 2, 2015 at 7:57:10 PM UTC-5, MA Laforge wrote:
>>
>> The real question is how much programming overhead is required to use
>> these types (assuming the compiler does the grunt work reducing the
>> *performance* overhead)
>>
>
> No, the real question is whether the benefit of using special types for
> radians vs. degrees would outweigh the costs of retraining every single
> user from every single previous mainstream programming language. To me,
> there is no contest ? doing angles differently from every other programming
> language would impose enormous costs in teaching, documentation, and
> support (imagine the never-ending flood of mailing-list questions) that
> would completely overwhelm the benefit of eliminating a "d" suffix on a few
> functions and automating a few angle conversions.

+1

One of the reasons the language from the MathWorks company is so
popular is that it lifts the burden of worring about types, memory
allocation, and a host of other issues from the backs of people who
only want to do math. Requring users to specify a type in order to
take a sin or cos (or sind or cosd) will make Julia very unpopular.

From what I understand, Julia uses types sparingly, and for two
reasons:

* When needed for high performance.
* As a way to do something like object-oriented programming.

As I understand it, types are not systematically required as a basic
part of writing a program to so ordinary users can become effective
at solving their math problem quickly. This is opposed to, say, C++,
which requires strict typing from the get-go, and is accordingly
difficult for non-programmers to use for doing math.

Since types should be used sparingly, I don't think it a good idea to
replace convenience functions like sind and cosd with a type-driven
invocation mechanism -- ordinary users will be confused.

Stuart

Patrick O'Leary

unread,
Mar 4, 2015, 9:04:30 AM3/4/15
to julia...@googlegroups.com
On Tuesday, March 3, 2015 at 2:57:28 PM UTC-6, Stuart Brorson wrote:
Since types should be used sparingly, I don't think it a good idea to
replace convenience functions like sind and cosd with a type-driven
invocation mechanism -- ordinary users will be confused.

You also can't replace all of them, since the inverse functions can't be dispatched in this way. Anecdotally, I use atan2d more than any of the other *d functions, typically as a step on the way to making a plot.

MA Laforge

unread,
Mar 4, 2015, 7:10:09 PM3/4/15
to julia...@googlegroups.com
Fair enough.  I don't want to stifle the adoption of Julia by other developers.

Maybe Ivar is correct: This might be better suited to be implemented as a 3rd party library.  Maybe SIUnits (https://github.com/Keno/SIUnits.jl)
Reply all
Reply to author
Forward
0 new messages