On 5/31/13 1:37 AM, Marco Inacio wrote:
>
>> Here's a nice discussion of the distinction in C++:
>>
>>
http://stackoverflow.com/questions/1632145/use-of-min-and-max-functions-in-c
>>
>> We absolutely need to keep the distinction as-is in the
>> C++ library for C++ compatibility, but that's a different
>> issue than keeping it in Stan.
> Nice SO link! Even after reading it though, I couldn't saw any problems arriving provided there's the specialization for
> (int, int).
I don't think there is a problem for Stan.
We just have to be careful not to break the
expected C++ behavior in our API. That means leaving
the fmin and fmax functions in place and behaving as
they currently behave.
>> It's going to be tricky, though, with the way Stan compiles.
>> It will just use max() for max() and it will try to call
>> the standard libraries unless we're careful to import our own
>> and our own have better type matches.
>
> I didn't know that, how does this happen? My guess was that there were a "using std;" in Stan compiled code, but I found
> none, so why would it call std::max? Is there a way I could simulate this behavior in a unit test to check which
> function is being called?
This is very confusing in C++.
Check out this description of abs(), with signature
int abs(int);
in <cstdlib>:
http://www.cplusplus.com/reference/cstdlib/abs/
You don't need an include to compile this program in
file abs.cpp:
#include <iostream>
int main() {
std::cout << "abs(-2.3)=" << abs(-2.3) << std::endl;
}
It has this rather unexpected behavior:
~/temp2$ clang++ abs.cpp
~/temp2$ ./a.out
abs(-2.3)=2
What's happening is that the double value -2.3 is getting
cast to an integer (-2) and then run through abs().
Turns out there's another abs() in <cmath> with three
overloaded signatures. Now compare this program:
#include <cmath>
#include <iostream>
int main() {
std::cout << "abs(-2.3)=" << abs(-2.3) << std::endl;
std::cout << "std::abs(-2.3)=" << std::abs(-2.3) << std::endl;
}
which as you might expect does this:
~/temp2$ clang++ abs2.cpp
~/temp2$ ./a.out
abs(-2.3)=2
std::abs(-2.3)=2.3
An explicit "using" seems to force the std::abs version
as seen in abs3.cpp:
#include <cmath>
#include <iostream>
int main() {
using std::abs;
std::cout << "abs(-2.3)=" << abs(-2.3) << std::endl;
std::cout << "std::abs(-2.3)=" << std::abs(-2.3) << std::endl;
}
which produces this:
~/temp2$ clang++ abs3.cpp
~/temp2$ ./a.out
abs(-2.3)=2.3
std::abs(-2.3)=2.3
Good unit test should be able to catch all this if there are
different behaviors. Otherwise, it's not really unit testable.
For lgamma, the error behavior was different.
I wouldn't worry about deprecation for the moment. Feel
free to just leave fabs() and fmin() and fmax() and change the
doc to indicate they're there for C++ lib compatibility.
- Bob