Re: [eigen] numerical differentiation

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


2009/9/27 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>:
> 2009/9/27 Thomas Capricelli <orzel@xxxxxxxxxxxxxxx>:
>>
>>
>> Well, anyway, i've put one in unsupported/NumericalDiff on my eigen fork, it
>> provides Forward and Central, with (quite basic) unit tests :
>>
>> http://bitbucket.org/orzel/eigen2-
>> cminpack/src/tip/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h
>> http://bitbucket.org/orzel/eigen2-
>> cminpack/src/tip/unsupported/test/NumericalDiff.cpp
>>
>> I use a template parameter 'mode' to select which one is used... and i have
>> two questions related to this:
>>
>> * in the code i use a switch(mode), in the hope that the compiler will
>> optimize this and only the relevant code will be compiled-in, and no test will
>> be made at run-time for the switch... can you confirm ?
>
> Yes, no problem. Since mode is explicitly known at compile time (as a
> template parameter), i know that at least GCC will always resolve the
> branching at compile time, even in full debug mode.
>
>>
>> * i'm afraid that the enum for the mode is cluttering the namespace.. how
>> could i do better ?
>
> Good question. This is a general problem that we have to solve before
> eigen3. For now, say that if it compiles it's OK.
>
> Ideas for general solutions:
> * use namespaced/typed enums. This is the clean solution, but it's
> hard to do without making the API cumbersome.
> Perhaps we could have small structs containing enums like
>
> struct NumericalDiffMode {
>  enum NumericalDiffMode {
>      Forward,
>      Central
>  };
> };
>
> and then a using-statement:
>
> using NumericalDiffMode::NumericalDiffMode;

OK, forget about the using-statement, that was stupid from me, but
anyway, I arrived to this very simple solution:

#include<iostream>

struct DiffMode { enum Type {Forward, Central}; };
struct Quark { enum Type {Charm, Strange }; };

void print_DiffMode(DiffMode::Type d)
{ std::cout << int(d) << std::endl; }

void print_Quark(Quark::Type q)
{ std::cout << int(q) << std::endl; }

int main()
{
  print_DiffMode(DiffMode::Forward);
  print_Quark(Quark::Strange);

  // but this doesn't compile, as the type mismatch is detected at compile time:
  // print_Quark(DiffMode::Forward);
  //
  // GCC 4.4 gives this good error message:
  // enums.cpp:32: error: cannot convert 'Eigen::DiffMode::Type' to
'Eigen::Quark::Type'
  // for argument '1' to 'void print_Quark(Eigen::Quark::Type)'
}

********************

What do you think of this?

The only cost to pay is the need to do  ::Type when referring to the enum type.

Would you prefer to do DiffMode_t instead of DiffMode::Type? If yes,
it's easy to make such typedefs automatically and generate the structs
with a variadic macro.

The only thing that we really can't achieve is to be able to refer to
the enum type as just DiffMode. Because we really want that type to be
a plain enum type, not a struct. It's true that in some cases we could
have structs, but in lots of other cases having enums allows to make
important code simplifications, like using these values in expressions
like " if(X==Y) " or your switch() statement here.

We also need to clarify one thing. So far we have avoided passing enum
template parameters, e.g.

template<DiffMode::Type blabla> class blabla;

What does the standard say? Perhaps this is actually well supported by
compilers? Would allow to greatly improve enum type safety...

Benoit



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/