In common Lisp, sin, cos, or tan, etc., only accept radian? For example, I would like to get a degree value from the below.
cosT = A , therefore, T = acosA.
In common Lisp, I get the result of "T" as a radian value. But, I'd like to get that as a normal degree. (e.g., cos60 = 0.5, and acos0.5 = 60) How could I convert radian to degree? Is there any function or macro to do this? Thanks for your help.
In article <3A38BE71.B8707...@solibri.com>, Martti Halminen
<martti.halmi...@solibri.com> wrote: > In the standard language there isn't a ready-built one for this, IIRC. > Allegro's Windows version seems to have one, maybe other > implementations, too.
> Writing your own isn't all that difficult:
> (defun deg-to-rad (degrees) (* pi (/ degrees 180.0)))
> or something like that. (Unless the compiler already did this?) > Rather less readable, though.
If the function were written: (defun rad-to-deg (radians) (* (/ 180 pi) radians)) I would expect it to perform simple constant folding and be just as efficient as using (* radians 57.29577951308232d0).
Martti Halminen <martti.halmi...@solibri.com> writes: > If for some odd reason you would need to do billions of these > transforms, a little faster version would be
then probably any non-stupid compiler will notice and do the constant calculation at compile-time. If you are dealing with a particularly non-optimizing compiler, you can force the calculation to read-time, e.g.
or use a constant (though a sufficiently dumb compiler might still refuse to inline the constant, so that you'd still have to use #.):
(declaim (type double-float rad-to-deg-conversion-factor)) (defconstant rad-to-deg-conversion-factor (/ 180.0d0 pi) "Factor used to convert radiants to degrees by multiplication.")
That should make it both more readable, and less error-prone. If the need for speed is even greater you could consider declaring rad-to-deg inline (or using compiler-macros for the same effect on implementations like Franz' ACL) and/or (after careful analysis!) reducing safety to 0.
Regs, Pierre.
-- Pierre R. Mai <p...@acm.org> http://www.pmsf.de/pmai/ The most likely way for the world to be destroyed, most experts agree, is by accident. That's where we come in; we're computer professionals. We cause accidents. -- Nathaniel Borenstein
>>>>> "Christopher" == Christopher J Vogt <v...@computer.org> writes:
Christopher> Martti Halminen wrote: >> If for some odd reason you would need to do billions of these >> transforms, a little faster version would be >> >> (defun rad-to-deg (radians) (* radians 57.29577951308232d0)) >> >> or something like that. (Unless the compiler already did this?) >> Rather less readable, though.
Christopher> If the function were written: Christopher> (defun rad-to-deg (radians) Christopher> (* (/ 180 pi) radians)) Christopher> I would expect it to perform simple constant folding Christopher> and be just as efficient as using (* radians Christopher> 57.29577951308232d0).
Except that pi is a long-float, so that would be (* radians 57.2957795....L0). (I always forget this because CMUCL's long-float = double-float.)
When you get timing results like this, it just means that the function you are timing takes less time than the resolution of the timer. One common way of getting (at least relative) timing information for very quick functions is to build a test function that calls it many times.
For example:
(defun test1 (n) (dotimes (i n) (rad-to-deg1 1.5)))
(defun test2 (n) (dotimes (i n) (rad-to-deg2 1.5)))
and then pick a value for N that gets you somewhere away from zero time.
It is also important to remember to compile the test functions, although since I recall that you use MCL, it does it for you.
A quick test of ACL (ver. 4.3) shows that the compiler will constant fold the second form, but not it will not rearrange the computation for constant folding in the first case:
Also, the second form (only) runs about 10% faster on a Sparc2.
USER> (time (time1 1000000)) ; cpu time (non-gc) 800 msec user, 10 msec system ; cpu time (gc) 40 msec user, 0 msec system ; cpu time (total) 840 msec user, 10 msec system ; real time 845 msec ; space allocation: ; 1 cons cell, 0 symbols, 24,000,032 other bytes NIL
USER> (time (time2 1000000)) ; cpu time (non-gc) 710 msec user, 0 msec system ; cpu time (gc) 50 msec user, 0 msec system ; cpu time (total) 760 msec user, 0 msec system ; real time 758 msec ; space allocation: ; 1 cons cell, 0 symbols, 24,000,032 other bytes NIL
I don't know the source of all of the 24 bytes of consing per function call. A double float requires 8 bytes of storage, and there is presumably one word (4 bytes) of overhead, so that would account for 12 bytes. I don't know why the other 12 bytes are allocated.
* "Pierre R. Mai" <p...@acm.org> | That should make it both more readable, and less error-prone. If the | need for speed is even greater you could consider declaring rad-to-deg | inline (or using compiler-macros for the same effect on | implementations like Franz' ACL) and/or (after careful analysis!) | reducing safety to 0.
I would have suggested a compiler macro on the trigonometric functions that looked for a conversion of the argument from degrees to radians, say with a form like (sin (degrees ...)), to do the computation and conversion with as little loss of precision as possible. This may be done only if you shadow the symbol in new package, since sin (etc) are in the common-lisp package and anyone else doing a similar compiler- macro would mess with yours.
#:Erik -- The United States of America, soon a Bush league world power. Yeee-haw!
In article <m3puiug6bi....@bjork.local.neodesic> on <m3puiug6bi....@bjork.local.neodesic>, "John Wiseman"
<wise...@bjork.local.neodesic> wrote: > It might be silly, but I always write this as
> (defun rad-to-deg (r) > (* #.(/ 180 pi) r))
CMUCL interprets #. correctly for this usage, but I don't think this syntax works on ACL. Can anyone confirm this?
-- -> -\-=-=-=-=-=-=-=-=-=-/^\-=-=-=<*><*>=-=-=-/^\-=-=-=-=-=-=-=-=-=-/- <- -> -/-=-=-=-=-=-=-=-=-=/ { Rahul -<>- Jain } \=-=-=-=-=-=-=-=-=-\- <- -> -\- "I never could get the hang of Thursdays." - HHGTTG by DNA -/- <- -> -/- http://photino.sid.rice.edu/ -=- mailto:rahul-j...@usa.net -\- <- |--|--------|--------------|----|-------------|------|---------|-----|-| Version 11.423.999.210020101.23.50110101.042 (c)1996-2000, All rights reserved. Disclaimer available upon request.
"Rahul Jain" <ra...@rice.edu> writes: > In article <m3puiug6bi....@bjork.local.neodesic> on > <m3puiug6bi....@bjork.local.neodesic>, "John Wiseman" > <wise...@bjork.local.neodesic> wrote:
> > It might be silly, but I always write this as
> > (defun rad-to-deg (r) > > (* #.(/ 180 pi) r))
> CMUCL interprets #. correctly for this usage, but I don't think this > syntax works on ACL. Can anyone confirm this?
Works in acl6_trial here. What could go wrong?
Cheers, M.
-- surely, somewhere, somehow, in the history of computing, at least one manual has been written that you could at least remotely attempt to consider possibly glancing at. -- Adam Rixey
Very interesting. =) I've got little different results. Here is my test result with MCL 4.0 on Powerbook G3 series 233MHz. --------------------------------------------------------------------------- - ? (defun rad-to-deg (radian) (/ (* radian 180.0) pi)) RAD-TO-DEG ? (defun test (n) (dotimes (i n) (rad-to-deg 1.5))) TEST ? (time (test 1000000)) (TEST 1000000) took 2,971 milliseconds (2.971 seconds) to run. Of that, 181 milliseconds (0.181 seconds) were spent in The Cooperative Multitasking Experience. 310 milliseconds (0.310 seconds) was spent in GC. 32,000,008 bytes of memory allocated. NIL ? --------------------------------------------------------------------------- - ? (defun rad-to-deg (radian) (* radian (/ 180.0 pi))) RAD-TO-DEG ? (defun test (n) (dotimes (i n) (rad-to-deg 1.5))) TEST ? (time (test 1000000)) (TEST 1000000) took 3,001 milliseconds (3.001 seconds) to run. Of that, 257 milliseconds (0.257 seconds) were spent in The Cooperative Multitasking Experience. 268 milliseconds (0.268 seconds) was spent in GC. 32,000,008 bytes of memory allocated. NIL ? --------------------------------------------------------------------------- - ? (defun rad-to-deg (radian) (* radian 57.29577951308232d0)) RAD-TO-DEG ? (defun test (n) (dotimes (i n) (rad-to-deg 1.5))) TEST ? (time (test 1000000)) (TEST 1000000) took 1,489 milliseconds (1.489 seconds) to run. Of that, 69 milliseconds (0.069 seconds) were spent in The Cooperative Multitasking Experience. 16,000,000 bytes of memory allocated. NIL ? --------------------------------------------------------------------------- - ? (defun rad-to-deg (radians) (declare (double-float radians) (optimize (speed 3) (safety 0))) (/ (* radians 180.0d0) pi)) RAD-TO-DEG ? (defun test (n) (dotimes (i n) (rad-to-deg 1.5))) TEST ? (time (test 1000000)) (TEST 1000000) took 2,960 milliseconds (2.960 seconds) to run. Of that, 212 milliseconds (0.212 seconds) were spent in The Cooperative Multitasking Experience. 262 milliseconds (0.262 seconds) was spent in GC. 32,000,008 bytes of memory allocated. NIL ? --------------------------------------------------------------------------- - ? (defun rad-to-deg (radians) (declare (double-float radians) (optimize (speed 3) (safety 0))) (* radians (/ 180.0d0 pi))) RAD-TO-DEG ? (defun test (n) (dotimes (i n) (rad-to-deg 1.5))) TEST ? (time (test 1000000)) (TEST 1000000) took 2,907 milliseconds (2.907 seconds) to run. Of that, 203 milliseconds (0.203 seconds) were spent in The Cooperative Multitasking Experience. 275 milliseconds (0.275 seconds) was spent in GC. 32,000,008 bytes of memory allocated. NIL ? --------------------------------------------------------------------------- -
Here, most fast result is third one which used '57.29577951308232d0' rather than (/ 180.0 pi). The time difference is as twice faster than others, and memory usage is just half as well. Hmm.. very interesting. Anyway, thanks to tell me about the 'test' tips. =)
Is there any way to correct this difference..? (In my case, 0.1d14 is same as nothing because I use this degree for an analysis of probabilities... But if I consider to use it with a different application which needs very very accurate result, then it might be a problem?) Thanks alot.
the correct response is to _ignore_ this difference. do not test for equality of floats, but compare the absolute value of their difference with some suitably small number. choosing the size of this small number is an exercise for the reader, not because i want to be rude, but because it varies with your end goals and choice of algorithm.
> (In my case, 0.1d14 is same as > nothing because I use this degree for an analysis of probabilities... But if > I consider to use it with a different application which needs very very > accurate result, then it might be a problem?) Thanks alot.
> the correct response is to _ignore_ this difference. do not test for > equality of floats, but compare the absolute value of their difference > with some suitably small number. choosing the size of this small > number is an exercise for the reader, not because i want to be rude, > but because it varies with your end goals and choice of algorithm.
>> CMUCL interprets #. correctly for this usage, but I don't think this >> syntax works on ACL. Can anyone confirm this?
> Works in acl6_trial here. What could go wrong?
Someone told me that the result of the evaluation was not insterted into the surrounding form. I guess it was either a bug which has since been fixed or a misunderstanding on our part. Thanks for clearing this up.
-- -> -/- - Rahul Jain - -\- <- -> -\- http://linux.rice.edu/~rahul -=- mailto:rahul-j...@usa.net -/- <- -> -/- "I never could get the hang of Thursdays." - HHGTTG by DNA -\- <- |--|--------|--------------|----|-------------|------|---------|-----|-| Version 11.423.999.220020101.23.50110101.042 (c)1996-2000, All rights reserved. Disclaimer available upon request.
> >> CMUCL interprets #. correctly for this usage, but I don't think this > >> syntax works on ACL. Can anyone confirm this?
> > Works in acl6_trial here. What could go wrong?
> Someone told me that the result of the evaluation was not insterted into > the surrounding form. I guess it was either a bug which has since been > fixed or a misunderstanding on our part. Thanks for clearing this up.
I hope CMUCL doesn't "interpret" #. rather than treating it as a standard reader macro. I believe CMUCL is a high-quality implementation and does the right thing, but "#." is a reader macro and has its effect at read time. A program naively calling READ has no way to kow whether or not #. was executed during the call to read. It _should_ have no way whereby it could know this (if *READ-EvAL* is true at read time).
I'm quite sure (as one of its implementors) that Allegro treats #. correctly, i.e., as a standard reader macro at read time, and that neither the evaluator or the compiler could in any way be cognizant whether some subform happened to be the result of a #. reader macro form. However, I'm also aware that the "#." syntax is required to fail (by signalling error) if a containing form is read when *READ-EVAL* is NIL. If you write code that contains "#.", you need to ensure that this code will be read in an environmentin which *READ-EVAL* is true.
Now, I really thing that smart compiles ought to do constant folding in places where it is "obvious to the programmer" that this constant folding is appropriate. ACL tries to do this for you, and I'm pretty sure that other implementations do this as well. But CL is a subtle language, and it uis advisable (in that small portion of inner-loop code where peformance actually makes a difference) to see the code that the compiler generates (DISASSEMBLE, profiling, or whatever other tools are provided) to make sure that the compiler is doing what you need. Don't just assume that it isn't, but also don't just assume that it is.
Anyway, it is hard to imagine an implementation in which treatment of "#." wold likely be an _efficiency_ issue.
> In common Lisp, sin, cos, or tan, etc., only accept radian? > For example, I would like to get a degree value from the below.
> cosT = A , therefore, T = acosA.
> In common Lisp, I get the result of "T" as a radian value. > But, I'd like to get that as a normal degree. > (e.g., cos60 = 0.5, and acos0.5 = 60) > How could I convert radian to degree?
Good Lord, haven't you ever gone to school and study geometry. Well, anyway, the full circle is 2P radian or 360deg. Can you convert from one to the other now <g>?