Created attachment 496 [details] Bzip file of the feature request with a test file I've made a custom scalar type in order to use the CADNA library (http://www-pequan.lip6.fr/cadna/) with eigen. This library was created to estimate the round-off error in a program. The include file linked permit to use it if you have already install CADNA on your computer. Due to the potential conflict between license, I don't link file coming from CADNA itself. CADNA library can be download here: http://www-pequan.lip6.fr/cadna//Download_Dir/register.php This is a pre-version with a test file to show the use of it. If this need more explanation, I can provide them.

If there is general interest in this and someone is willing to maintain it, I would not object adding this as an unsupported module (similar to Adolc, MPFR modules)

This might also be useful to write precision oriented unit tests of our numerical algorithms. Regarding the patch, it is currently lacking a proper unit test with the associated FindCADNA.cmake file and CMakeLists.txt change to find CADNA and enable the unit test. This is necessary to include it as an unsupported module.

It's not a real problem for me to maintain it. It's not a big code so it'll be with pleasure. I've make unit test at this point but I can work on them to know if their is no problem at all. In fact even if this is not include in Eigen, I've for project to do it to try my code. The cmake part could be more complicated for me because I never used it before but I can learn.

We can handle the cmake stuff. For the unit test you can take inspiration from unsupported/test/mpreal_support.cpp. btw, note that when using a double_st type instead of double inside Eigen, then the order of operations won't be necessarily the same as Eigen's algorithms will follow different optimization paths.

I need some help to create the unit test. In fact, I've some trouble to print the cadna type. Their is a function to print it in the cadna library but I'm not able to link it to the special type in eigen. Does it exist a function for the cast or the printing that I didn't find?

(In reply to Romain Picot from comment #5) > Does it exist a function for the cast or the printing that I didn't find? Does overloading this work? std::ostream& operator<<(std::ostream&, const cadna_type&); To cast a matrix write this: A.cast<double>(); This requires that converting your Scalar to double is implemented. If that does not work out of the box, specialize this function: namespace Eigen{ namespace internal { template<> inline double cast<cadna_type,double>(const cadna_type& x) {...} }} Neither of the above should be strictly necessary for unit tests but of course would be very good to have.

I've try the second way and it's work. So now, I'll continue to create the test. I've some trouble with it so I don't really know when they'll come but I'm working on it.

Not to distract from the focus of this bug, but I have been looking into CADNA as a possible approach to writing better unit tests for Eigen, and I am trying to understand how CADNA compares to interval arithmetic. After looking at CADNA source code and playing with a small example, it seems that a CADNA "stochastic number" is a triple x,y,z or numbers, and an integer describing the number of significant digits. The implementation of arithmetic operation then operates on x,y,z separately, each time with the rounding mode set randomly between FE_DOWNWARD and FE_UPWARD. These CADNA types support conversion to ordinary scalars; the converted value is just the mean, (x+y+z)/3. I've been looking at all the examples for a clue as to what advantage this might offer over interval arithmetic, but all of the examples seem to be just as well served by interval arithmetic. Downsides compared to a typical interval arithmetic implementation include: - non-deterministic (randomized) results; - harder-to-interprete results; - slower (especially as it sets rounding modes for each operation) - unsafe (implicit conversion to ordinary numbers).

(In reply to Benoit Jacob from comment #8) > Not to distract from the focus of this bug, but I have been looking into > CADNA as a possible approach to writing better unit tests for Eigen, and I > am trying to understand how CADNA compares to interval arithmetic. > > After looking at CADNA source code and playing with a small example, it > seems that a CADNA "stochastic number" is a triple x,y,z or numbers, and an > integer describing the number of significant digits. > > The implementation of arithmetic operation then operates on x,y,z > separately, each time with the rounding mode set randomly between > FE_DOWNWARD and FE_UPWARD. > > These CADNA types support conversion to ordinary scalars; the converted > value is just the mean, (x+y+z)/3. > > I've been looking at all the examples for a clue as to what advantage this > might offer over interval arithmetic, but all of the examples seem to be > just as well served by interval arithmetic. > > Downsides compared to a typical interval arithmetic implementation include: > - non-deterministic (randomized) results; > - harder-to-interprete results; > - slower (especially as it sets rounding modes for each operation) > - unsafe (implicit conversion to ordinary numbers). First of all, about the principle you're in the true. The idea is to modify the rounding mode to treat efficiently the round-off error. Using probability law you have the precision of your result with the amount of digit (the integer in fact). It's another way of testing your code in fact. About your listing what I can say: -You can have a non-modify seed for each test. You can look at the cadna_init function. It's a determined seed unless you modify it. -Results can be harder to interprete due to some problem but for me it's like when interval arithmetic give you a result between -inf and +inf. -Slower yes, it's a testing tools so not some code you'll run everyday. -The implicit conversion that you point out is done when you cast a stochastic number. If you just wanna print it you can use the str function which convert stochastic number to a number with the significant digits calculated as a string. One main advantage is the amount of modification needed to use it. With interval arithmetic you'll need to modify some function to found min and max of your starting interval. About the progression of the unit test: I'm trying to test basic operation, and the maximum amount of eigen internal function. Due to the random which can occur between to computer, I rather prefer to try to use function without error than comparing value which can be different.

Created attachment 503 [details] first draft of unit test with minor modification of the template I've modify the template to use the cast<real>() function. Two version of unit test: -one which is a pretty good copy paste of the mpreal test unit with some minor modification to modify the type and use the stochastic type. -one where test is only done one without verification on value. Just to test if operation compile and run in fact. I rather recommend the second approach. Due to probabilistic approach, and the round-off modification, you can easily have value near of 0 and have error so the test stop depending of the seed. This is a draft of unit test with some modification to do but wanna have some return on the idea of working only on the second option.

It would not really check implementation correctness, without any verifications, would it? It would especially be good to have tests that use the specific features of CADNA. Can you try relaxing the epsilons (especially dummy_precision) to make more tests pass? Also, try separating the test into smaller tests to simplify testing individual components (mpreal_support might not be a good example for that, but check any other test file for CALL_SUBTEST_*). And of course, before committing we need a FindCADNA.cmake (check the other Find*.cmake files for inspiration) -- but we can help you with that.

Another question, is this really the best way to cast a CADNA type to a POD? template<> inline float cast<float_st,float>(const float_st& x) { char ch[25]; x.str(ch); float res = atof(ch); return res; }

-- GitLab Migration Automatic Message -- This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/888.