## digitalmars.D - support for various angular units in std.math

- Colin Wallace (16/16) Feb 27 2011 I've been doing a lot of opengl work in D. Opengl deals primarily
- Simen kjaeraas (10/26) Feb 27 2011 I think a better solution would be a proper units struct:
- Walter Bright (4/14) Feb 27 2011 I appreciate the suggestion, but suspect that adding a parallel set of t...
- Andrei Alexandrescu (10/24) Feb 28 2011 Agreed. What would add value is a units library that refuses calls to
- bearophile (5/11) Feb 28 2011 Have you seen Don's answer?
- KB (8/8) Feb 28 2011 For a very tidy and typesafe implementation of units I would recommend c...
- Peter Alexander (7/23) Feb 28 2011 When you start doing OpenGL properly, degrees don't show up at all. In
- Trass3r (1/4) Feb 28 2011 I think you even have to do that in OpenGL 4 (maybe even 3).
- Peter Alexander (2/6) Feb 28 2011 Yep, I'm pretty sure you're right.
- Don (7/13) Feb 28 2011 Actually, it isn't!
- Colin Wallace (2/9) Feb 28 2011 That's a very marginal error (1e-19). For graphics, I never need that mu...
- Don (9/20) Mar 01 2011 Yes, but someone doing high school trigonometry with degrees will be

I've been doing a lot of opengl work in D. Opengl deals primarily (maybe even completely?) with degrees. When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward, but I still think it would be nice if there were some built in functions for dealing with other units than radians. I think a system that looked like what is used for the Duration struct in core.time would make things more readable. The code for taking the sine of a number measured in degrees could look like: sin!"degrees"(45) rather than sin(45*PI/180) It doesn't make a huge difference to me, but neither does the dur!() function, yet somebody decided it would be helpful and it made its way into the standard library. So I figured I would at least share this idea to see what other people thought of it.

Feb 27 2011

Colin Wallace <wallacoloo gmail.com> wrote:I've been doing a lot of opengl work in D. Opengl deals primarily (maybe even completely?) with degrees. When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward, but I still think it would be nice if there were some built in functions for dealing with other units than radians. I think a system that looked like what is used for the Duration struct in core.time would make things more readable. The code for taking the sine of a number measured in degrees could look like: sin!"degrees"(45) rather than sin(45*PI/180) It doesn't make a huge difference to me, but neither does the dur!() function, yet somebody decided it would be helpful and it made its way into the standard library. So I figured I would at least share this idea to see what other people thought of it.I think a better solution would be a proper units struct: unit!"degrees" a; sin(a); // Automagically behaves correctly bool foo(unit!"radians" bar) { return bar < PI; } foo(a); // Compile-time error: degrees not equal to radians. -- Simen

Feb 27 2011

Colin Wallace wrote:When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward, but I still think it would be nice if there were some built in functions for dealing with other units than radians. I think a system that looked like what is used for the Duration struct in core.time would make things more readable. The code for taking the sine of a number measured in degrees could look like: sin!"degrees"(45) rather than sin(45*PI/180)I appreciate the suggestion, but suspect that adding a parallel set of trig functions that do nothing more than multiply the arg by a constant is more cognitive load for the user than benefit.

Feb 27 2011

On 2/28/11 12:49 AM, Walter Bright wrote:Colin Wallace wrote:Agreed. What would add value is a units library that refuses calls to e.g. trig functions unless the user specifically inserts a conversion. That is, instead of sin!"degrees"(x); you'd use: sin(to!"degrees"(x)); That way the conversion remains explicit but is hoisted out of the multitude of math functions. AndreiWhen using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward, but I still think it would be nice if there were some built in functions for dealing with other units than radians. I think a system that looked like what is used for the Duration struct in core.time would make things more readable. The code for taking the sine of a number measured in degrees could look like: sin!"degrees"(45) rather than sin(45*PI/180)I appreciate the suggestion, but suspect that adding a parallel set of trig functions that do nothing more than multiply the arg by a constant is more cognitive load for the user than benefit.

Feb 28 2011

Andrei:you'd use: sin(to!"degrees"(x)); That way the conversion remains explicit but is hoisted out of the multitude of math functions.Have you seen Don's answer? http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=130757 Bye, bearophile

Feb 28 2011

For a very tidy and typesafe implementation of units I would recommend checking out the units feature in F#. http://blogs.msdn.com/b/andrewkennedy/archive/2008/08/29/units-of-measure-in-f-part-one-introducing-units.aspx Probably not the best link, but the compiler will flag if units are not consistent in computations. Also accept they adopt a 'tagging' system to declare units, but conversely it is very extensable to any set of defined units. K

Feb 28 2011

On 28/02/11 1:17 AM, Colin Wallace wrote:I've been doing a lot of opengl work in D. Opengl deals primarily (maybe even completely?) with degrees. When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward, but I still think it would be nice if there were some built in functions for dealing with other units than radians. I think a system that looked like what is used for the Duration struct in core.time would make things more readable. The code for taking the sine of a number measured in degrees could look like: sin!"degrees"(45) rather than sin(45*PI/180) It doesn't make a huge difference to me, but neither does the dur!() function, yet somebody decided it would be helpful and it made its way into the standard library. So I figured I would at least share this idea to see what other people thought of it.When you start doing OpenGL properly, degrees don't show up at all. In fact, I believe all degrees functions are deprecated in the latest version (could be wrong on this). Really, you should be doing all the matrix calculations and rotations yourself. If anything should come out of this, it would be a nice, small linear algebra library.

Feb 28 2011

Really, you should be doing all the matrix calculations and rotations yourself. If anything should come out of this, it would be a nice, small linear algebra library.I think you even have to do that in OpenGL 4 (maybe even 3).

Feb 28 2011

On 28/02/11 10:12 AM, Trass3r wrote:Yep, I'm pretty sure you're right.Really, you should be doing all the matrix calculations and rotations yourself. If anything should come out of this, it would be a nice, small linear algebra library.I think you even have to do that in OpenGL 4 (maybe even 3).

Feb 28 2011

Colin Wallace wrote:I've been doing a lot of opengl work in D. Opengl deals primarily (maybe even completely?) with degrees. When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward,Actually, it isn't! assert(sin(360 * PI / 180 ) == 0.0); // fails! There are supposed to be sinPi(), cosPi(), tanPi() functions, but they are not yet implemented (they are quite difficult to get right). You should use: sinPi(360/180); to get sine in degrees.

Feb 28 2011

Don Wrote:Colin Wallace wrote:That's a very marginal error (1e-19). For graphics, I never need that much precision. Besides, it has nothing to do with the conversion in this case. sin(2*PI) results in the same value, causing the assertion to fail.When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward,Actually, it isn't! assert(sin(360 * PI / 180 ) == 0.0); // fails!

Feb 28 2011

Colin Wallace wrote:Don Wrote:Yes, but someone doing high school trigonometry with degrees will be confused when it fails.Colin Wallace wrote:That's a very marginal error (1e-19). For graphics, I never need that much precision.When using trigonometric functions, they all deal with radians. So I've been having to do lots of converting. Converting is very straightforward,Actually, it isn't! assert(sin(360 * PI / 180 ) == 0.0); // fails!Besides, it has nothing to do with the conversion in this case. sin(2*PI) results in the same value, causing the assertion to fail.No, it's the conversion. It's because the mathematical number pi is not precisely representable in floating point. But 360 is precisely representable, and sin(360 degrees) is also precisely representable. assert(sinPi(360/180) == 0) will pass. So multiplying by PI is *not* the correct way to calculate trignometric functions in degrees. 2*PI is not 360 degrees.

Mar 01 2011