Thread overview | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 18, 2005 std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Right now in std.math2 there are several "min" and "max" and various other high-level math overloads. For example min(int x, int y), min(long x, long y), min(real x, real y), min(int[] x), min(long[] x), min(real[] x). I'd like to replace those with template min(T:T[]) { T min(T[] x) { T res = T.max; foreach(T val; x) { if (val < res) res = val; } return res; } } template min(T) { T min(T[] x ...) { return min!(T[])(x); } } User code would look like, for example, min!(int)(10, 20) min!(short)(x, 10) max!(double)(10, 33.33, -PI, 2*PI, 0); int[] nums = ...; int bound = max!(int[])(nums); With inlining the simple calls with just two elements should be just as fast as exising solutions. I could also see using templates for sum, too, and maybe even sqr, sign and abs. I suppose documenting std.math2 would also be worthwhile. Then again putting some of the more useful definitions in std.math and leaving std.math2 be is another option. I don't know what the original design of math/math2 was for. Thoughts? |
August 18, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | Sounds good to me , I use my own handrolled templates for these already , as a part of phobos would be much better ... and math2 isn't document or even mentioned in the official docs , be nice to have a refrence for it. Not sure why math2 even exists, why not throw them all in math ? Charlie "Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:de2hb4$1pf$1@digitaldaemon.com... > Right now in std.math2 there are several "min" and "max" and various other > high-level math overloads. For example min(int x, int y), min(long x, long > y), min(real x, real y), > min(int[] x), min(long[] x), min(real[] x). > I'd like to replace those with > template min(T:T[]) { > T min(T[] x) { > T res = T.max; > foreach(T val; x) { > if (val < res) res = val; > } > return res; > } > } > template min(T) { > T min(T[] x ...) { return min!(T[])(x); } > } > > User code would look like, for example, > min!(int)(10, 20) > min!(short)(x, 10) > max!(double)(10, 33.33, -PI, 2*PI, 0); > int[] nums = ...; > int bound = max!(int[])(nums); > With inlining the simple calls with just two elements should be just as fast > as exising solutions. > I could also see using templates for sum, too, and maybe even sqr, sign and > abs. I suppose documenting std.math2 would also be worthwhile. Then again putting some of the more useful definitions in std.math and leaving std.math2 be is another option. I don't know what the original design of math/math2 was for. > > Thoughts? > > |
August 18, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles | "Charles" <noone@nowhere.com> wrote in message news:de3034$fhe$1@digitaldaemon.com... > Sounds good to me , I use my own handrolled templates for these already , > as > a part of phobos would be much better ... and math2 isn't document or even > mentioned in the official docs , be nice to have a refrence for it. > > Not sure why math2 even exists, why not throw them all in math ? Yeah, I'm thinking that would make sense, too. Here's the contents of math2 for those who haven't opened it lately. A couple of ideas come to mind: 1) deprecate feq now that we have feqrel 2) deprecate toString and atof since they are in std.string 3) deprecate conversions between angle units 4) move everything else to std.math with templates for the overloaded functions bit feq(real a, real b) bit feq(real a, real b, real eps) int abs(int n) long abs(long n) real abs(real n) int sqr(int n) long sqr(long n) real sqr(real n) real trunc(real n) real frac(real n) real poly(real x, real[] coefficients) int sign(int n) int sign(long n) int sign(real n) real cycle2deg(real c) real cycle2rad(real c) real cycle2grad(real c) real deg2cycle(real d) real deg2rad(real d) real deg2grad(real d) real rad2deg(real r) real rad2cycle(real r) real rad2grad(real r) real grad2deg(real g) real grad2cycle(real g) real grad2rad(real g) real avg(real[] n) int sum(int[] n) long sum(long[] n) real sum(real[] n) int min(int[] n) long min(long[] n) real min(real[] n) int min(int a, int b) long min(long a, long b) real min(real a, real b) int max(int[] n) long max(long[] n) real max(real[] n) int max(int a, int b) long max(long a, long b) real max(real a, real b) real acot(real x) real asec(real x) real acosec(real x) real cot(real x) real sec(real x) real cosec(real x) real coth(real x) real sech(real x) real cosech(real x) real acosh(real x) real asinh(real x) real atanh(real x) real acoth(real x) real asech(real x) real acosech(real x) real atof(char[] s) char[] toString(real x) |
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | I agree. The date in math2 is 2002 -- things have changed a lot since then. Some of that stuff is a bit bizarre -- who uses grads????
abs() is the most important thing in there, but why isn't it an intrinsic?
A compiler can do tricks like:
// eliminates a poorly predictable branch
int fastAbs(int x)
{
asm {
mov EAX, [x];
cdq;
xor EAX, EDX;
sub EAX, EDX;
}
}
(not generally applicable because it only works for EAX, EDX, won't optimise well in general).
I could imagine a processor including abs in its instruction set.
But as a minimum it should be in std.math.
A comment about your templates for max,min:
with sum and avg, when using floats/doubles, you should be accumulating in a real. Likewise ints should accumulate in a long.
Might be nice to also have a template for these cases which returned 'long' for integral types, 'real' for floats, ireal for imaginary, creal for complex, and passed user defined types straight through.
[[ ... except, if your type was (say) MyPolyType!(double), you might
want to upgrade it to a MyPolyType!(real) ... nice idea, but probably never required. ]]
Does sqr() deserve to be in there? It doesn't add any value that I can see.
Also I'm not sure that sign() is useful since we have signbit() in std.math -- when would you use it?
Likewise, all the auxilliary trig funcs (cot, sec, cosec, coth,..) can be trivially generated from the standard ones. I think that unless there's some accuracy subtleties or a speed advantage, it's hard to justify something so simple. Especially since the use of asm in that case probably _inhibits_ optimisation! eg 2.5 * cot(x) should become
2.5/tan(x).
-Don.
Ben Hinkle wrote:
> "Charles" <noone@nowhere.com> wrote in message news:de3034$fhe$1@digitaldaemon.com...
>
>>Sounds good to me , I use my own handrolled templates for these already , as
>>a part of phobos would be much better ... and math2 isn't document or even
>>mentioned in the official docs , be nice to have a refrence for it.
>>
>>Not sure why math2 even exists, why not throw them all in math ?
>
>
> Yeah, I'm thinking that would make sense, too. Here's the contents of math2 for those who haven't opened it lately. A couple of ideas come to mind:
> 1) deprecate feq now that we have feqrel
> 2) deprecate toString and atof since they are in std.string
> 3) deprecate conversions between angle units
> 4) move everything else to std.math with templates for the overloaded functions
>
> bit feq(real a, real b)
> bit feq(real a, real b, real eps)
> int abs(int n)
> long abs(long n)
> real abs(real n)
> int sqr(int n)
> long sqr(long n)
> real sqr(real n)
> real trunc(real n)
> real frac(real n)
> real poly(real x, real[] coefficients)
> int sign(int n)
> int sign(long n)
> int sign(real n)
> real cycle2deg(real c)
> real cycle2rad(real c)
> real cycle2grad(real c)
> real deg2cycle(real d)
> real deg2rad(real d)
> real deg2grad(real d)
> real rad2deg(real r)
> real rad2cycle(real r)
> real rad2grad(real r)
> real grad2deg(real g)
> real grad2cycle(real g)
> real grad2rad(real g)
> real avg(real[] n)
> int sum(int[] n)
> long sum(long[] n)
> real sum(real[] n)
> int min(int[] n)
> long min(long[] n)
> real min(real[] n)
> int min(int a, int b)
> long min(long a, long b)
> real min(real a, real b)
> int max(int[] n)
> long max(long[] n)
> real max(real[] n)
> int max(int a, int b)
> long max(long a, long b)
> real max(real a, real b)
> real acot(real x)
> real asec(real x)
> real acosec(real x)
> real cot(real x)
> real sec(real x)
> real cosec(real x)
> real coth(real x)
> real sech(real x)
> real cosech(real x)
> real acosh(real x)
> real asinh(real x)
> real atanh(real x)
> real acoth(real x)
> real asech(real x)
> real acosech(real x)
> real atof(char[] s)
> char[] toString(real x)
>
>
|
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | "Don Clugston" <dac@nospam.com.au> wrote in message news:de387d$msf$1@digitaldaemon.com... >I agree. The date in math2 is 2002 -- things have changed a lot since then. Some of that stuff is a bit bizarre -- who uses grads???? > abs() is the most important thing in there, but why isn't it an intrinsic? > > A compiler can do tricks like: > > // eliminates a poorly predictable branch > int fastAbs(int x) > { > asm { > mov EAX, [x]; > cdq; > xor EAX, EDX; > sub EAX, EDX; > } > } > (not generally applicable because it only works for EAX, EDX, won't > optimise well in general). > I could imagine a processor including abs in its instruction set. > But as a minimum it should be in std.math. ok > A comment about your templates for max,min: > with sum and avg, when using floats/doubles, you should be accumulating in > a real. Likewise ints should accumulate in a long. > Might be nice to also have a template for these cases which returned > 'long' for integral types, 'real' for floats, ireal for imaginary, creal > for complex, and passed user defined types straight through. Good point. I was actually thinking avg would stay as a real-only function since averaging a bunch of ints will probably result in a non-int. Maybe it can support float/double but the rest of std.math deals with reals. How about only min/max work with generic types, sum works with anything and returns long or real and avg only works with real. > [[ ... except, if your type was (say) MyPolyType!(double), you might > want to upgrade it to a MyPolyType!(real) ... nice idea, but probably > never required. ]] > > Does sqr() deserve to be in there? It doesn't add any value that I can see. yeah - the only thing I could think of was that expr needs to be written out twice expr*expr instead of once sqr(expr). But that's not worth a whole function, I agree. > Also I'm not sure that sign() is useful since we have signbit() in std.math -- when would you use it? I'm on the fence with that since taking the sign of an int shouldn't have to go through signbit(real). To me this is on the save level as abs(). > Likewise, all the auxilliary trig funcs (cot, sec, cosec, coth,..) can be > trivially generated from the standard ones. I think that unless there's > some accuracy subtleties or a speed advantage, it's hard to justify > something so simple. Especially since the use of asm in that case probably > _inhibits_ optimisation! eg 2.5 * cot(x) should become > 2.5/tan(x). agreed. deprecate. > -Don. > > > > Ben Hinkle wrote: >> "Charles" <noone@nowhere.com> wrote in message news:de3034$fhe$1@digitaldaemon.com... >> >>>Sounds good to me , I use my own handrolled templates for these already , >>>as >>>a part of phobos would be much better ... and math2 isn't document or >>>even >>>mentioned in the official docs , be nice to have a refrence for it. >>> >>>Not sure why math2 even exists, why not throw them all in math ? >> >> >> Yeah, I'm thinking that would make sense, too. Here's the contents of >> math2 for those who haven't opened it lately. A couple of ideas come to >> mind: >> 1) deprecate feq now that we have feqrel >> 2) deprecate toString and atof since they are in std.string >> 3) deprecate conversions between angle units >> 4) move everything else to std.math with templates for the overloaded >> functions >> >> bit feq(real a, real b) >> bit feq(real a, real b, real eps) >> int abs(int n) >> long abs(long n) >> real abs(real n) >> int sqr(int n) >> long sqr(long n) >> real sqr(real n) >> real trunc(real n) >> real frac(real n) >> real poly(real x, real[] coefficients) >> int sign(int n) >> int sign(long n) >> int sign(real n) >> real cycle2deg(real c) >> real cycle2rad(real c) >> real cycle2grad(real c) >> real deg2cycle(real d) >> real deg2rad(real d) >> real deg2grad(real d) >> real rad2deg(real r) >> real rad2cycle(real r) >> real rad2grad(real r) >> real grad2deg(real g) >> real grad2cycle(real g) >> real grad2rad(real g) >> real avg(real[] n) >> int sum(int[] n) >> long sum(long[] n) >> real sum(real[] n) >> int min(int[] n) >> long min(long[] n) >> real min(real[] n) >> int min(int a, int b) >> long min(long a, long b) >> real min(real a, real b) >> int max(int[] n) >> long max(long[] n) >> real max(real[] n) >> int max(int a, int b) >> long max(long a, long b) >> real max(real a, real b) >> real acot(real x) >> real asec(real x) >> real acosec(real x) >> real cot(real x) >> real sec(real x) >> real cosec(real x) >> real coth(real x) >> real sech(real x) >> real cosech(real x) >> real acosh(real x) >> real asinh(real x) >> real atanh(real x) >> real acoth(real x) >> real asech(real x) >> real acosech(real x) >> real atof(char[] s) >> char[] toString(real x) >> |
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | Ben Hinkle wrote: > "Don Clugston" <dac@nospam.com.au> wrote in message news:de387d$msf$1@digitaldaemon.com... > >>I agree. The date in math2 is 2002 -- things have changed a lot since then. Some of that stuff is a bit bizarre -- who uses grads???? >>abs() is the most important thing in there, but why isn't it an intrinsic? >> >>A compiler can do tricks like: >> >>// eliminates a poorly predictable branch >>int fastAbs(int x) >>{ >> asm { >> mov EAX, [x]; >> cdq; >> xor EAX, EDX; >> sub EAX, EDX; >> } >>} >>(not generally applicable because it only works for EAX, EDX, won't optimise well in general). >>I could imagine a processor including abs in its instruction set. >>But as a minimum it should be in std.math. > > > ok > > >>A comment about your templates for max,min: >>with sum and avg, when using floats/doubles, you should be accumulating in a real. Likewise ints should accumulate in a long. >>Might be nice to also have a template for these cases which returned 'long' for integral types, 'real' for floats, ireal for imaginary, creal for complex, and passed user defined types straight through. > > > Good point. I was actually thinking avg would stay as a real-only function since averaging a bunch of ints will probably result in a non-int. Maybe it can support float/double but the rest of std.math deals with reals. How about only min/max work with generic types, sum works with anything and returns long or real and avg only works with real. Let the user decide with a second parameter. > >>[[ ... except, if your type was (say) MyPolyType!(double), you might >>want to upgrade it to a MyPolyType!(real) ... nice idea, but probably never required. ]] >> >>Does sqr() deserve to be in there? It doesn't add any value that I can see. > > > yeah - the only thing I could think of was that expr needs to be written out twice expr*expr instead of once sqr(expr). But that's not worth a whole function, I agree. Any time you need to write something twice you've introduced the potential for error (during maintenance, or just by having a side effect) and made the code harder to read. It stays. >>Likewise, all the auxilliary trig funcs (cot, sec, cosec, coth,..) can be trivially generated from the standard ones. I think that unless there's some accuracy subtleties or a speed advantage, it's hard to justify something so simple. Especially since the use of asm in that case probably _inhibits_ optimisation! eg 2.5 * cot(x) should become >>2.5/tan(x). > > > agreed. deprecate. So you're going to deprecate all the trigonometric functions, since they are all simple relationships on pi? These do provide an important purpose: they tell the reader what he's doing, instead of telling him how he's doing it. Would you really see "1 / sin (x)" and go "oh right he's getting the cosecant", particularly if that's embedded in a much larger calculation? |
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Burton Radons | >>>A comment about your templates for max,min: >>>with sum and avg, when using floats/doubles, you should be accumulating >>>in a real. Likewise ints should accumulate in a long. >>>Might be nice to also have a template for these cases which returned >>>'long' for integral types, 'real' for floats, ireal for imaginary, creal >>>for complex, and passed user defined types straight through. >> >> Good point. I was actually thinking avg would stay as a real-only function since averaging a bunch of ints will probably result in a non-int. Maybe it can support float/double but the rest of std.math deals with reals. How about only min/max work with generic types, sum works with anything and returns long or real and avg only works with real. > > Let the user decide with a second parameter. What do you mean? >>>Does sqr() deserve to be in there? It doesn't add any value that I can see. >> >> yeah - the only thing I could think of was that expr needs to be written out twice expr*expr instead of once sqr(expr). But that's not worth a whole function, I agree. > > Any time you need to write something twice you've introduced the potential for error (during maintenance, or just by having a side effect) and made the code harder to read. It stays. sheesh - you're a flexible one aren't ya. :-) fine, it stays (hands on hips) >>>Likewise, all the auxilliary trig funcs (cot, sec, cosec, coth,..) can be trivially generated from the standard ones. I think that unless there's some accuracy subtleties or a speed advantage, it's hard to justify something so simple. Especially since the use of asm in that case probably _inhibits_ optimisation! eg 2.5 * cot(x) should become 2.5/tan(x). >> >> agreed. deprecate. > > So you're going to deprecate all the trigonometric functions, since they are all simple relationships on pi? These do provide an important purpose: they tell the reader what he's doing, instead of telling him how he's doing it. Would you really see "1 / sin (x)" and go "oh right he's getting the cosecant", particularly if that's embedded in a much larger calculation? I agree cosecant and friends do come up but hyperbolic arccotangent? yikes. But since you're standing up for them I'll let Don see if he cares enough to argue (ps - I don't really care if they stay or go). |
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | Ben Hinkle wrote: >>>>A comment about your templates for max,min: >>>>with sum and avg, when using floats/doubles, you should be accumulating in a real. Likewise ints should accumulate in a long. >>>>Might be nice to also have a template for these cases which returned 'long' for integral types, 'real' for floats, ireal for imaginary, creal for complex, and passed user defined types straight through. >>> >>>Good point. I was actually thinking avg would stay as a real-only function since averaging a bunch of ints will probably result in a non-int. Maybe it can support float/double but the rest of std.math deals with reals. How about only min/max work with generic types, sum works with anything and returns long or real and avg only works with real. >> >>Let the user decide with a second parameter. > > > What do you mean? > > >>>>Does sqr() deserve to be in there? It doesn't add any value that I can see. >>> >>>yeah - the only thing I could think of was that expr needs to be written out twice expr*expr instead of once sqr(expr). But that's not worth a whole function, I agree. >> >>Any time you need to write something twice you've introduced the potential for error (during maintenance, or just by having a side effect) and made the code harder to read. It stays. Well, you could write pow(expr, 2). A problem I have with sqr() is that some languages use "sqr" instead of "sqrt" (VB perhaps?). >>So you're going to deprecate all the trigonometric functions, since they are all simple relationships on pi? No, there are subtleties involved in some functions. These do provide an important >>purpose: they tell the reader what he's doing, instead of telling him how he's doing it. Would you really see "1 / sin (x)" and go "oh right he's getting the cosecant", particularly if that's embedded in a much larger calculation? Personally, I always hate seeing "cosec" in a formula, I always translate it into 1/sin in my head ... but that's just my prejudice. I don't really have a problem with any of these functions being included, but there is a philosophical question... how many functions will there eventually be in std.math ? I can see three options: (a) Follow C, and C++ with a minimalist approach to std.math, and deprecate those functions. (b) Include them in std.math, even if it means std.math will eventually become very large. (c) Put trivial derived functions in a seperate file. Maybe std.math2 ? :-) In any case, I do think it is important to have a policy, so that it is reasonably predictable where functions will be, rather than an ad-hoc approach. |
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | > I don't really have a problem with any of these functions being included,
> but there is a philosophical question...
> how many functions will there eventually be in std.math ?
>
> I can see three options:
> (a) Follow C, and C++ with a minimalist approach to std.math, and
> deprecate those functions.
> (b) Include them in std.math, even if it means std.math will eventually
> become very large.
> (c) Put trivial derived functions in a seperate file. Maybe std.math2 ?
> :-)
>
> In any case, I do think it is important to have a policy, so that it is reasonably predictable where functions will be, rather than an ad-hoc approach.
That's a good question. Another concern I have is where to put the complex functions. Note std.math has sqrt(creal) already (I imagine to nicely overload the other sqrts) and more overloads will come soon. Given D's overloading rules I think std.math is going to get big. I am in the process of adding abs(creal) which just calls hypot. I'm not going to bother to add overloads for the pure-imaginary types but for completeness I wouldn't be surprised if they end up in there. If the complex functions went into another module I'd say they should have a "c" prefix since mixing real and creal will be common when doing complex math.
I think a big std.math is ok, though. The compiler is fast. The doc is manageable. And one doesn't have to guess if a function is trivial or not enough to import std.math or std.math2.
|
August 19, 2005 Re: std.math2 proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | In article <de3ma1$1325$1@digitaldaemon.com>, Don Clugston says... > >Ben Hinkle wrote: >>>>>A comment about your templates for max,min: >>>>>with sum and avg, when using floats/doubles, you should be accumulating >>>>>in a real. Likewise ints should accumulate in a long. >>>>>Might be nice to also have a template for these cases which returned >>>>>'long' for integral types, 'real' for floats, ireal for imaginary, creal >>>>>for complex, and passed user defined types straight through. >>>> >>>>Good point. I was actually thinking avg would stay as a real-only function since averaging a bunch of ints will probably result in a non-int. Maybe it can support float/double but the rest of std.math deals with reals. How about only min/max work with generic types, sum works with anything and returns long or real and avg only works with real. >>> >>>Let the user decide with a second parameter. >> >> >> What do you mean? >> >> >>>>>Does sqr() deserve to be in there? It doesn't add any value that I can see. >>>> >>>>yeah - the only thing I could think of was that expr needs to be written out twice expr*expr instead of once sqr(expr). But that's not worth a whole function, I agree. >>> >>>Any time you need to write something twice you've introduced the potential for error (during maintenance, or just by having a side effect) and made the code harder to read. It stays. > >Well, you could write pow(expr, 2). >A problem I have with sqr() is that some languages use "sqr" instead of >"sqrt" (VB perhaps?). > >>>So you're going to deprecate all the trigonometric functions, since they are all simple relationships on pi? > >No, there are subtleties involved in some functions. > > >These do provide an important >>>purpose: they tell the reader what he's doing, instead of telling him how he's doing it. Would you really see "1 / sin (x)" and go "oh right he's getting the cosecant", particularly if that's embedded in a much larger calculation? > >Personally, I always hate seeing "cosec" in a formula, I always translate it into 1/sin in my head ... but that's just my prejudice. > >I don't really have a problem with any of these functions being >included, but there is a philosophical question... >how many functions will there eventually be in std.math ? > >I can see three options: >(a) Follow C, and C++ with a minimalist approach to std.math, and >deprecate those functions. >(b) Include them in std.math, even if it means std.math will eventually >become very large. >(c) Put trivial derived functions in a seperate file. Maybe std.math2 ? :-) > >In any case, I do think it is important to have a policy, so that it is reasonably predictable where functions will be, rather than an ad-hoc approach. (c) makes sense to me.. I think probably the original idea behind math2 was: std.math was supposed to contain basically what a C programmer would expect in math.h, and then 'std.math2' would contain other things that really belong in a math lib. somewhere (for example, abs is in C's stdlib.h). I like your idea - get everything important in std.math regardless of what a C progammer would intuit, and put the less often used functions in std.math2. |
Copyright © 1999-2021 by the D Language Foundation