digitalmars.D - std.math2 proposal
- Ben Hinkle (31/31) Aug 18 2005 Right now in std.math2 there are several "min" and "max" and various oth...
- Charles (9/40) Aug 18 2005 Sounds good to me , I use my own handrolled templates for these already ...
- Ben Hinkle (68/73) Aug 18 2005 Yeah, I'm thinking that would make sense, too. Here's the contents of ma...
- Don Clugston (38/118) Aug 18 2005 I agree. The date in math2 is 2002 -- things have changed a lot since
- Ben Hinkle (14/134) Aug 18 2005 ok
- Burton Radons (11/73) Aug 18 2005 Any time you need to write something twice you've introduced the
- Ben Hinkle (6/42) Aug 18 2005 sheesh - you're a flexible one aren't ya. :-)
- Don Clugston (20/55) Aug 18 2005 Well, you could write pow(expr, 2).
- Ben Hinkle (12/25) Aug 19 2005 That's a good question. Another concern I have is where to put the compl...
- Dave (8/63) Aug 19 2005 (c) makes sense to me..
- Ben Hinkle (9/11) Aug 19 2005 What actually would be really cool is having generic algorithms to compu...
- Don Clugston (17/32) Aug 21 2005 I'm not entirely sure that the generic functions like min(), sum()
- Ben Hinkle (18/44) Aug 22 2005 Where would you put min/sum/etc?
- Burton Radons (28/83) Aug 22 2005 These functions switch on the traits of a comparable type - there are
- Ben Hinkle (3/25) Aug 22 2005 Neat. I didn't know that.
- Burton Radons (12/43) Aug 23 2005 I mean that min/max is part of a much broader set of template mixins
- Walter (4/5) Aug 21 2005 Because of Pavel's copyright on it. The stuff needs to be reimplemented ...
- Don Clugston (53/53) Aug 21 2005 While we're on the subject, here's another quick function which exposes
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?
Aug 18 2005
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 asfastas exising solutions. I could also see using templates for sum, too, and maybe even sqr, signandabs. 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?
Aug 18 2005
"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)
Aug 18 2005
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)
Aug 18 2005
"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.okA 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)
Aug 18 2005
Ben Hinkle wrote:"Don Clugston" <dac nospam.com.au> wrote in message news:de387d$msf$1 digitaldaemon.com...Let the user decide with a second parameter.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.okA 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.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.[[ ... 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.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?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.
Aug 18 2005
What do you mean?Let the user decide with a second parameter.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.sheesh - you're a flexible one aren't ya. :-) fine, it stays (hands on hips)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.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.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).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?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.
Aug 18 2005
Ben Hinkle wrote:Well, you could write pow(expr, 2). A problem I have with sqr() is that some languages use "sqr" instead of "sqrt" (VB perhaps?).What do you mean?Let the user decide with a second parameter.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.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.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.No, there are subtleties involved in some functions. These do provide an importantSo you're going to deprecate all the trigonometric functions, since they are all simple relationships on pi?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.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?
Aug 18 2005
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.
Aug 19 2005
In article <de3ma1$1325$1 digitaldaemon.com>, Don Clugston says...Ben Hinkle wrote:(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.Well, you could write pow(expr, 2). A problem I have with sqr() is that some languages use "sqr" instead of "sqrt" (VB perhaps?).What do you mean?Let the user decide with a second parameter.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.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.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.No, there are subtleties involved in some functions. These do provide an importantSo you're going to deprecate all the trigonometric functions, since they are all simple relationships on pi?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.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?
Aug 19 2005
(b) Include them in std.math, even if it means std.math will eventually become very large.What actually would be really cool is having generic algorithms to compute the various special functions (probably just using something brute-force like the power series) and use those for complex and arbitrary-precision versions (see http://home.comcast.net/~benhinkle/gmp-d/). That would be really cool to have all the standard math functions (including min/max and friends) that just work for ints, reals, creals and arbitrary-precision floats. I should add arbitrary-precision complex to gmp-d and then that could work, too. Anyway... I'm just dreaming out loud here about what a *nice* std.math would look like. :-)
Aug 19 2005
Ben Hinkle wrote:I'm not entirely sure that the generic functions like min(), sum() belong in std.math. But, if there were generic algorithms for power series, I might change my mind. My "gut feel" is that std.math is for functions that operate on and return real numbers, std.complex or std.cmath would operate on complex or imaginary numbers. Template functions like "min" could be applied in non-mathematical contexts (eg, you might want to find the smallest FunkyWidget), One possibility is to follow the STL from C++ and create a std.algorithm. Of course the STL made some very strange decisions, accumulate() isn't with the other functions, for example. ---- With Walters comment about Pavel's copyright, I suggest that std.math2 be moved to etc for the time being. Or at least, don't bother documenting it. Just throw abs() into std.math, it's important and trivial.(b) Include them in std.math, even if it means std.math will eventually become very large.What actually would be really cool is having generic algorithms to compute the various special functions (probably just using something brute-force like the power series) and use those for complex and arbitrary-precision versions (see http://home.comcast.net/~benhinkle/gmp-d/). That would be really cool to have all the standard math functions (including min/max and friends) that just work for ints, reals, creals and arbitrary-precision floats. I should add arbitrary-precision complex to gmp-d and then that could work, too. Anyway... I'm just dreaming out loud here about what a *nice* std.math would look like. :-)
Aug 21 2005
"Don Clugston" <dac nospam.com.au> wrote in message news:deb35e$1rre$1 digitaldaemon.com...Ben Hinkle wrote:Where would you put min/sum/etc?I'm not entirely sure that the generic functions like min(), sum() belong in std.math. But, if there were generic algorithms for power series, I might change my mind.(b) Include them in std.math, even if it means std.math will eventually become very large.What actually would be really cool is having generic algorithms to compute the various special functions (probably just using something brute-force like the power series) and use those for complex and arbitrary-precision versions (see http://home.comcast.net/~benhinkle/gmp-d/). That would be really cool to have all the standard math functions (including min/max and friends) that just work for ints, reals, creals and arbitrary-precision floats. I should add arbitrary-precision complex to gmp-d and then that could work, too. Anyway... I'm just dreaming out loud here about what a *nice* std.math would look like. :-)My "gut feel" is that std.math is for functions that operate on and return real numbers, std.complex or std.cmath would operate on complex or imaginary numbers.The problem with using multiple modules is that D's overloading rules are very strict and so user code can't import both std.math and std.complex and freely mix calls to functions overloaded between modules. So for example if sin was defined in std.math and std.complex then writing sin(x) would be illegal - it would have to be explicitly written as std.math.sin(x) or std.complex.sin(x) or users would have to alias sin in the current module. So with D if there's a chance two modules will be used at the same time they should not overload each other. Personally I think using std.math for "all things mathematical" is natural. Even mathematical operations like min/max that can be applied to anything that overloads < or > or whatever. It's still most commonly used as a mathematical operation. Maybe we need std.math and std.mathwannabes.Template functions like "min" could be applied in non-mathematical contexts (eg, you might want to find the smallest FunkyWidget), One possibility is to follow the STL from C++ and create a std.algorithm. Of course the STL made some very strange decisions, accumulate() isn't with the other functions, for example.Sounds reasonable - and std.math can import whatever has the min/max/etc so that user code doesn't have to import lots of stuff just to do basic math operations.
Aug 22 2005
Ben Hinkle wrote:"Don Clugston" <dac nospam.com.au> wrote in message news:deb35e$1rre$1 digitaldaemon.com...These functions switch on the traits of a comparable type - there are also traits for arrays, strings, numerics, integrals, fractionals and complex (that's where std.math comes in), and others to work with. A library organisation could have it as: module std.tcomparable; template TComparable(T) { T min(T[] list...) { assert (list.length); T result = list[0]; foreach (T item; list[1..$]) if (item < result) result = item; return result; } } But I don't think it's worth doing this to Phobos, because it's such a large restructuring. By the way, that's the only implementation of min you need - you can pass an array to a variadics-array-taking function.Ben Hinkle wrote:Where would you put min/sum/etc?I'm not entirely sure that the generic functions like min(), sum() belong in std.math. But, if there were generic algorithms for power series, I might change my mind.(b) Include them in std.math, even if it means std.math will eventually become very large.What actually would be really cool is having generic algorithms to compute the various special functions (probably just using something brute-force like the power series) and use those for complex and arbitrary-precision versions (see http://home.comcast.net/~benhinkle/gmp-d/). That would be really cool to have all the standard math functions (including min/max and friends) that just work for ints, reals, creals and arbitrary-precision floats. I should add arbitrary-precision complex to gmp-d and then that could work, too. Anyway... I'm just dreaming out loud here about what a *nice* std.math would look like. :-)Yeah, it's a real pain in the ass how D makes writing functions a mandatory part of its engineering but supports them so horribly. The same problem applies to mixins. The claim is that this way prevents bugs, but what it really does is put pitfalls into developing and maintaining code. D's very simple function overloading will still catch any ambiguous conflict.My "gut feel" is that std.math is for functions that operate on and return real numbers, std.complex or std.cmath would operate on complex or imaginary numbers.The problem with using multiple modules is that D's overloading rules are very strict and so user code can't import both std.math and std.complex and freely mix calls to functions overloaded between modules. So for example if sin was defined in std.math and std.complex then writing sin(x) would be illegal - it would have to be explicitly written as std.math.sin(x) or std.complex.sin(x) or users would have to alias sin in the current module. So with D if there's a chance two modules will be used at the same time they should not overload each other.Personally I think using std.math for "all things mathematical" is natural. Even mathematical operations like min/max that can be applied to anything that overloads < or > or whatever. It's still most commonly used as a mathematical operation. Maybe we need std.math and std.mathwannabes.Template functions like "min" could be applied in non-mathematical contexts (eg, you might want to find the smallest FunkyWidget), One possibility is to follow the STL from C++ and create a std.algorithm. Of course the STL made some very strange decisions, accumulate() isn't with the other functions, for example.Sounds reasonable - and std.math can import whatever has the min/max/etc so that user code doesn't have to import lots of stuff just to do basic math operations.
Aug 22 2005
I don't follow - what large restructuring? Aren't we just talking about std.math2?Where would you put min/sum/etc?These functions switch on the traits of a comparable type - there are also traits for arrays, strings, numerics, integrals, fractionals and complex (that's where std.math comes in), and others to work with. A library organisation could have it as: module std.tcomparable; template TComparable(T) { T min(T[] list...) { assert (list.length); T result = list[0]; foreach (T item; list[1..$]) if (item < result) result = item; return result; } } But I don't think it's worth doing this to Phobos, because it's such a large restructuring.By the way, that's the only implementation of min you need - you can pass an array to a variadics-array-taking function.Neat. I didn't know that.
Aug 22 2005
Ben Hinkle wrote:I mean that min/max is part of a much broader set of template mixins that have specialised, stunted forms all throughout Phobos; std.string is a specialisation of a string mixin, std.math is a fractional mixin (specifically a specialisation on the floating-point types to use the intrinsics - the general form would use approximating algorithms), array properties are a miniscule subset of an array mixin. It would be very valuable to have those templates in a standard library; they'd have richer functionality and they would work with user types. However, I don't think it's worth trying to reform Phobos to such an extent. I'm not talking about a template library like MinTL - instead one that purely functions with the builtin types.I don't follow - what large restructuring? Aren't we just talking about std.math2?Where would you put min/sum/etc?These functions switch on the traits of a comparable type - there are also traits for arrays, strings, numerics, integrals, fractionals and complex (that's where std.math comes in), and others to work with. A library organisation could have it as: module std.tcomparable; template TComparable(T) { T min(T[] list...) { assert (list.length); T result = list[0]; foreach (T item; list[1..$]) if (item < result) result = item; return result; } } But I don't think it's worth doing this to Phobos, because it's such a large restructuring.
Aug 23 2005
"Charles" <noone nowhere.com> wrote in message news:de3034$fhe$1 digitaldaemon.com...Not sure why math2 even exists, why not throw them all in math ?Because of Pavel's copyright on it. The stuff needs to be reimplemented to get around it, or math2 needs to be moved into etc.
Aug 21 2005
While we're on the subject, here's another quick function which exposes the x86 "fsincos" asm instruction. C99 considered including cis() but eventually rejected it; but I think the argument is stronger for D since (a) D has mandated the use of IEEE floats (and therefore x86 is a very significant platform), and (b) complex reals are more strongly embedded in the language. Might belong in std.cmath or std.complex, rather than std.math. ------------------------------------------------- SOME DOC CHANGES FOR std.math: The documentation for sin(x) in VC++2003 states: "If x is greater than or equal to 2^63, or less than or equal to -2^63 a loss of significance in the result occurs." That's a massive understatement. In fact, outside this range the results from the fsin, fcos instructions are nonsense. sin(1e20) returns 1e20. So the docs for sin(x), cos(x), cis(x) should state: "sin(x) is valid only for abs(x) < 0x1p+63 (approx 9e18). Outside this range, the results are undefined." tan(x) seems to be unaffected by this. Also, in the "constants" section, it might be helpful to add the line: "These are the closest representable numbers to the corresponding mathematical constant. Because the precision is not infinite, results may not be what you expect. For example, sin(2*PI) will not be <i>exactly<i> zero; instead, it will be about 1e-20 on most systems." There should be one line descriptions of what each constant is, as well. Trivial, but it would bring the docs closer to 1.0. -Don. ------------------------------------------------------ // cis(theta) = cos(theta) + sin(theta)i. version (X86) { // On x86, this is almost twice as fast as sin(x) + 1.0i*cos(x). creal cis(real x) { asm { fld x; fsincos; fxch st(1), st(0); } } } else { creal cis(real x) { return cos(x) + sin(x)*1i; } } unittest { assert(cis(0)==1+0i); assert(cis(1.3e5)==cos(1.3e5)+sin(1.3e5)*1i); creal c = cis(real.nan); assert(isnan(c.re) && isnan(c.im)); c = cis(real.infinity); assert(isnan(c.re) && isnan(c.im)); }
Aug 21 2005