November 17, 2010
On 11/17/10 2:42 PM, Michel Fortin wrote:
> Le 2010-11-17 ? 16:36, Andrei Alexandrescu a ?crit :
>
>> On 11/17/10 1:09 PM, Don Clugston wrote:
>>> Move the following functions from std.math into std.mathspecial:
>>> erf()
>>> erfc()
>>> lgamma() ----->   name changes to logGamma(real x)
>>> tgamma() --->   name changes to gamma(real x).
>>> BTW The 't' in the C name exists for extremely silly historical reasons.
>>>
>>> std.math will retain alias for these functions, before they are eventually deprecated.
>>
>> deprecated("Please use the homonym functions in std.mathspecial.")
>
> But won't that just become a convenient excuse to forget putting the deprecation notice in the documentation? It sounds redundant:
>
> /**
>   * Blah blah blah...
>   * Deprecated: use the homonym functions in std.mathspecial.
>   */
> deprecated("use the homonym functions in std.mathspecial")
> double lgamma(double);

I thought it's pretty clear that having active deprecation notes is not redundant at all. The right solution to avoiding redundancy is to have ddoc insert the deprecation note in the generated text.

Andrei
November 17, 2010
Don Clugston <dclugston at googlemail.com> wrote:

>>> (1) Add two necessary functions to std.math:
>>>
>>> // Rounds x to the nearest int or long using the currently selected
>>> rounding mode
>>> // (MUCH faster than cast(int)).
>>
>> Why isn't this the default, i.e. why doesn't cast(int) do this?
>
> Because C stuffed up in a major way, and we have to live with it. Intel has tried THREE TIMES to fix C's mistake, by making hardware changes and adding new instructions to their CPUs.

Sure, I can see the value in 'it's what C does'. Now, seeing as (int)1.0f does not compile in D, is there really a problem defining cast(int)1.0f to use this new, magical function? I'm not trying to be obnoxious, I just am.

-- 
Simen
November 17, 2010
On Wednesday, November 17, 2010 14:31:16 Andrei Alexandrescu wrote:
> On 11/17/10 1:56 PM, Simen Kjaeraas wrote:
> > David Simcha <dsimcha at gmail.com> wrote:
> >>> (1) Add two necessary functions to std.math:
> >>> 
> >>> // Rounds x to the nearest int or long using the currently selected
> >>> rounding mode
> >>> // (MUCH faster than cast(int)).
> >> 
> >> Why isn't this the default, i.e. why doesn't cast(int) do this?
> > 
> > Second this. If it's not so complex Walter can't possibly understand it, or it may cause bees to spurt from your floppy drive, it sounds like what cast(int) should do.
> 
> cast(int) always truncates, whereas Don's function uses the current
> rounding mode.

Then the question is whether there is a way to do what Don did, only have it truncate, and still have that sort of speed increase. If there is, then that's probably what cast(int) should do. If not, then cast(int) should be left as is.

- Jonathan M Davis
November 17, 2010
Le 2010-11-17 ? 17:47, Andrei Alexandrescu a ?crit :

> On 11/17/10 2:42 PM, Michel Fortin wrote:
>> But won't that just become a convenient excuse to forget putting the deprecation notice in the documentation? It sounds redundant:
>> 
>> /**
>>  * Blah blah blah...
>>  * Deprecated: use the homonym functions in std.mathspecial.
>>  */
>> deprecated("use the homonym functions in std.mathspecial")
>> double lgamma(double);
> 
> I thought it's pretty clear that having active deprecation notes is not redundant at all. The right solution to avoiding redundancy is to have ddoc insert the deprecation note in the generated text.

Ok, so now you have two places where you can write your deprecation notes instead of one, but only one will make the compiler output a helpful error message?

What if one day you want to deprecate functions informally (in the documentation only) and at a later time you want to deprecate them formally (making the compiler complain), should you coppy all your ddoc-style deprecated sections to a string following the deprecated keyword?

Is there any advantage in using the deprecated("note") syntax instead of making the compiler use the existing Deprecated section of ddoc to print a helpful comment?

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



November 17, 2010
On Wednesday, November 17, 2010 15:30:00 Michel Fortin wrote:
> Le 2010-11-17 ? 17:47, Andrei Alexandrescu a ?crit :
> > On 11/17/10 2:42 PM, Michel Fortin wrote:
> >> But won't that just become a convenient excuse to forget putting the deprecation notice in the documentation? It sounds redundant:
> >> 
> >> /**
> >> 
> >>  * Blah blah blah...
> >>  * Deprecated: use the homonym functions in std.mathspecial.
> >>  */
> >> 
> >> deprecated("use the homonym functions in std.mathspecial")
> >> double lgamma(double);
> > 
> > I thought it's pretty clear that having active deprecation notes is not redundant at all. The right solution to avoiding redundancy is to have ddoc insert the deprecation note in the generated text.
> 
> Ok, so now you have two places where you can write your deprecation notes instead of one, but only one will make the compiler output a helpful error message?
> 
> What if one day you want to deprecate functions informally (in the documentation only) and at a later time you want to deprecate them formally (making the compiler complain), should you coppy all your ddoc-style deprecated sections to a string following the deprecated keyword?
> 
> Is there any advantage in using the deprecated("note") syntax instead of making the compiler use the existing Deprecated section of ddoc to print a helpful comment?

It sounds to me like Michel wants the compiler to take the deprecation note from the ddoc comment and use it for both the documentation and the compiler's deprecation note whereas Andrei wants to put the deprecation note in the code and have ddoc take that and add it as a deprecation note in the ddoc when generating the ddoc. So, it's a question of which place you put the note. It ends up in both places either way.

- Jonathan M Davis
November 17, 2010
On Wed, 17 Nov 2010 17:46:57 -0500, Don Clugston <dclugston at googlemail.com> wrote:
>>> (1) Add two necessary functions to std.math:
>>>
>>> // Rounds x to the nearest int or long using the currently selected
>>> rounding mode
>>> // (MUCH faster than cast(int)).
>>
>> Why isn't this the default, i.e. why doesn't cast(int) do this?
>
> Because C stuffed up in a major way, and we have to live with it. Intel has tried THREE TIMES to fix C's mistake, by making hardware changes and adding new instructions to their CPUs.
>
>> Please use full words when abbr is not absolutely obvious and/or the
>> gain in typing is small (esp for rarely used functions).
>>  (also sgngamma --> signgamma)
>
> I didn't invent the name. sgn is the signum function. See, for example, http://en.wikipedia.org/wiki/Sign_function
>
>> To an uninitiated reader this may look like "random int" and "random long".
>
> Ugh, you're right.
>
>> Could we define this instead?
>> N roundTo(N)(real x) if (isIntegral!N);
>
> That sounds a bit too formal. I would expect that to perform some
> exact form of rounding (certainly not round-to-nearest, which seems
> irrational to our uninitiated reader). I would also expect it to do
> something sensible when the value is > int.max.
> This function should really be an intrinsic, and it only makes sense
> for int and long.
>
> fastRoundInt(real x)
> fastRoundLong(real x)
> ?
> A bit clumsy, but should be unambiguous.
>

Personally, I've already switched to using roundTo!T in my code. The function is over in std.conv, behaves as expected and supports a wide range of types. In contrast std.math has a multitude of functions (lround, lrint, rndtol) some of which have _never_ been implemented (lround) and others appear to be aliases of each other (lrint, rndtol). (This may just be incorrect documentation as rndtonl and rndtol are described differently). This is to say nothing of the floating point rounding functions (nearbyint, rint, round, rndtonl). Given that we have control over the floating point rounding mode, is there a reason we need anything more than round and roundTo!T?
November 17, 2010
On 11/17/10 3:30 PM, Michel Fortin wrote:
> Le 2010-11-17 ? 17:47, Andrei Alexandrescu a ?crit :
>
>> On 11/17/10 2:42 PM, Michel Fortin wrote:
>>> But won't that just become a convenient excuse to forget putting the deprecation notice in the documentation? It sounds redundant:
>>>
>>> /**
>>>   * Blah blah blah...
>>>   * Deprecated: use the homonym functions in std.mathspecial.
>>>   */
>>> deprecated("use the homonym functions in std.mathspecial")
>>> double lgamma(double);
>>
>> I thought it's pretty clear that having active deprecation notes is not redundant at all. The right solution to avoiding redundancy is to have ddoc insert the deprecation note in the generated text.
>
> Ok, so now you have two places where you can write your deprecation notes instead of one, but only one will make the compiler output a helpful error message?
>
> What if one day you want to deprecate functions informally (in the documentation only) and at a later time you want to deprecate them formally (making the compiler complain), should you coppy all your ddoc-style deprecated sections to a string following the deprecated keyword?
>
> Is there any advantage in using the deprecated("note") syntax instead of making the compiler use the existing Deprecated section of ddoc to print a helpful comment?

The advantage is that the deprecation error message will hint the user on what to do to fix things.

Andrei
November 17, 2010
Le 2010-11-17 ? 18:40, Andrei Alexandrescu a ?crit :

> On 11/17/10 3:30 PM, Michel Fortin wrote:
>> Le 2010-11-17 ? 17:47, Andrei Alexandrescu a ?crit :
>> 
>>> On 11/17/10 2:42 PM, Michel Fortin wrote:
>>>> But won't that just become a convenient excuse to forget putting the deprecation notice in the documentation? It sounds redundant:
>>>> 
>>>> /**
>>>>  * Blah blah blah...
>>>>  * Deprecated: use the homonym functions in std.mathspecial.
>>>>  */
>>>> deprecated("use the homonym functions in std.mathspecial")
>>>> double lgamma(double);
>>> 
>>> I thought it's pretty clear that having active deprecation notes is not redundant at all. The right solution to avoiding redundancy is to have ddoc insert the deprecation note in the generated text.
>> 
>> Ok, so now you have two places where you can write your deprecation notes instead of one, but only one will make the compiler output a helpful error message?
>> 
>> What if one day you want to deprecate functions informally (in the documentation only) and at a later time you want to deprecate them formally (making the compiler complain), should you coppy all your ddoc-style deprecated sections to a string following the deprecated keyword?
>> 
>> Is there any advantage in using the deprecated("note") syntax instead of making the compiler use the existing Deprecated section of ddoc to print a helpful comment?
> 
> The advantage is that the deprecation error message will hint the user on what to do to fix things.

Can't the compiler do the same by extracting the deprecated note from the ddoc comment?

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



November 17, 2010
On 11/17/10 5:36 PM, Michel Fortin wrote:
>> The advantage is that the deprecation error message will hint the user on what to do to fix things.
>
> Can't the compiler do the same by extracting the deprecated note from the ddoc comment?

It could. I'd find that rather bizarre. Why are we even debating this?

Andrei
November 18, 2010
On Wed, 2010-11-17 at 22:09 +0100, Don Clugston wrote:
> I have a pile of functions I wrote for Tango, most of which are part of C99. I'd like to move them into Phobos. In the process, I'd like to clean up a few things in std.math.
> 
> The main idea is that a new module, std.mathspecial, will contain
> mathematical Special Functions. In the long term, there could be quite
> a large number of these, but I think it will still be OK to have all
> of them declared in a single module.
> The implementations of these functions will mostly reside in
> std.internal.math.XXX. In many cases, the implementations are quite
> large.
> 
> std.math will be restricted to low-level operations and "high school" mathematics.

I think this is an excellent idea.


> (1) Add two necessary functions to std.math:
> 
> // Rounds x to the nearest int or long using the currently selected
> rounding mode
> // (MUCH faster than cast(int)).
> int rndint(real x)
> long rndlong(real x)

What would be the difference between these and rint() and lrint(), which
are already in std.math?


> (2) Delete etc.gamma

I didn't even know this module existed.  I recently implemented the gamma function myself, based on the same source (Cephes).  If I'd known about this it would have saved me quite a bit of time, so I say yes, let's bring it out of hiding.


> (3) Create a new module std.mathspecial.
> 
> Move the following functions from std.math into std.mathspecial:
> erf()
> erfc()
> lgamma() -----> name changes to logGamma(real x)
> tgamma() ---> name changes to gamma(real x).
> BTW The 't' in the C name exists for extremely silly historical reasons.
> 
> std.math will retain alias for these functions, before they are eventually deprecated.

Absolutely.   Most people will never need these functions, but it's very nice for scientific programmers to have them in the standard library.


> (4) Add implementations of those functions into std.internal.math.gammafunction
> Also add:
> real sgnGamma(real x);    // the sign of gamma(x), always used with logGamma.
> real digamma(x);   //  The digamma function
> real beta(real x, real y);    // the beta function
> 
> I'm not sure about the naming for the other functions. I will leave
> that for a later discussion.
> They include:
> * Distribution functions for the normal, F, chi-square, students-T, gamma, beta,
> poisson, binomial, and negative binomial distributions.
> * Cylindrical Bessel functions
> real cylBessel_j0(real x)  real cylBessel_y0(real x)
> real cylBessel_j1(real x)  real cylBessel_y1(real x)
> real cylBessel_jn(int n, real x )  real cylBessel_yn(int n, real x)

Regarding the Bessel functions, I suggest we use Mathematica's naming scheme.  There, the (cylindrical) Bessel functions are called BesselJ[n,z], BesselY[n,z], etc.  For D, that would be

  besselJ0(z)
  besselJ1(z)
  besselJ(n,z)

and so on.

I recently ported some of the modified Bessel functions (I_0, I_1, K_0, and K_1) from Cephes.  I could polish the code a bit, add implementations for general n, and submit that to std.mathspecial if you're interested.

-Lars