From: Jan B. <bie...@tu...> - 2008-01-23 11:35:31
Attachments:
biermann.vcf
|
Hi developers, I just downloaded the latest libmesh version and when I compile it in complex mode, the compiler throws an error from distributed_vector.h: In member function »Real DistributedVector<T>::min() const [with T = std::complex<double>]«: src/numerics/numeric_vector.C:182: instantiated from here /libmesh/include/numerics/distributed_vector.h:695: error: ungültiges static_cast vom Typ »const std::complex<double>« in den Typ »double« (and the same for the Real DistributedVector<T>::max() ) The wired thing is though, that my 2.5 years old version of libmesh has exactly the same line in the code that throws an error in the new version but it works ( double local_min = static_cast<double>(*std::min(_values.begin(), _values.end()));). So what changed since? Thanks, Jan |
From: John P. <pet...@cf...> - 2008-01-23 15:33:16
|
Jan Biermann writes: > Hi developers, >=20 > I just downloaded the latest libmesh version and when I compile it i= n > complex mode, the compiler throws an error from distributed=5Fvector= .h: >=20 > In member function =BBReal DistributedVector<T>::min() const [with T= =3D > std::complex<double>]=AB: > src/numerics/numeric=5Fvector.C:182: instantiated from here > /libmesh/include/numerics/distributed=5Fvector.h:695: error: ung=FCl= tiges > static=5Fcast vom Typ =BBconst std::complex<double>=AB in den Typ =BB= double=AB >=20 > (and the same for the Real DistributedVector<T>::max() ) >=20 > The wired thing is though, that my 2.5 years old version of libmesh = has > exactly the same line in the code that throws an error in the new > version but it works ( double local=5Fmin =3D > static=5Fcast<double>(*std::min(=5Fvalues.begin(), =5Fvalues.end()))= ;). >=20 > So what changed since=3F I'm not sure what's changed... Roy has factored out some MPI routines into the Parallel:: namespace, but this isn't the problem. What is the= proper way of casting from from complex to double anyway=3F Does it ju= st take the real part=3F Is that what we want for min/max=3F -John |
From: Roy S. <roy...@ic...> - 2008-01-23 15:49:01
|
On Wed, 23 Jan 2008, John Peterson wrote: > Jan Biermann writes: > > Hi developers, > > > > I just downloaded the latest libmesh version and when I compile it in > > complex mode, the compiler throws an error from distributed_vector.h: > > > > In member function »Real DistributedVector<T>::min() const [with T = > > std::complex<double>]«: > > src/numerics/numeric_vector.C:182: instantiated from here > > /libmesh/include/numerics/distributed_vector.h:695: error: ungültiges > > static_cast vom Typ »const std::complex<double>« in den Typ »double« > > > > (and the same for the Real DistributedVector<T>::max() ) > > > > The wired thing is though, that my 2.5 years old version of libmesh has > > exactly the same line in the code that throws an error in the new > > version but it works ( double local_min = > > static_cast<double>(*std::min(_values.begin(), _values.end()));). > > > > So what changed since? > > I'm not sure what's changed... Roy has factored out some MPI routines > into the Parallel:: namespace, but this isn't the problem. What is the > proper way of casting from from complex to double anyway? Does it just > take the real part? Is that what we want for min/max? Is that line of code even correct for Reals? std::min isn't supposed to operate on container iterators, it's just supposed to return the minimum of two elements with a defined operator<. There's a std::min_element which is probably what the author (I hope it wasn't me...) was thinking of. --- Roy |
From: John P. <pet...@cf...> - 2008-01-23 16:16:18
|
Roy Stogner writes: >=20 >=20 > On Wed, 23 Jan 2008, John Peterson wrote: >=20 > > Jan Biermann writes: > > > Hi developers, > > > > > > I just downloaded the latest libmesh version and when I compile = it in > > > complex mode, the compiler throws an error from distributed=5Fve= ctor.h: > > > > > > In member function =BBReal DistributedVector<T>::min() const [wi= th T =3D > > > std::complex<double>]=AB: > > > src/numerics/numeric=5Fvector.C:182: instantiated from here > > > /libmesh/include/numerics/distributed=5Fvector.h:695: error: ung= =FCltiges > > > static=5Fcast vom Typ =BBconst std::complex<double>=AB in den Ty= p =BBdouble=AB > > > > > > (and the same for the Real DistributedVector<T>::max() ) > > > > > > The wired thing is though, that my 2.5 years old version of libm= esh has > > > exactly the same line in the code that throws an error in the ne= w > > > version but it works ( double local=5Fmin =3D > > > static=5Fcast<double>(*std::min(=5Fvalues.begin(), =5Fvalues.end= ()));). > > > > > > So what changed since=3F > > > > I'm not sure what's changed... Roy has factored out some MPI routi= nes > > into the Parallel:: namespace, but this isn't the problem. What i= s the > > proper way of casting from from complex to double anyway=3F Does = it just > > take the real part=3F Is that what we want for min/max=3F >=20 > Is that line of code even correct for Reals=3F std::min isn't suppo= sed > to operate on container iterators, it's just supposed to return the > minimum of two elements with a defined operator<. There's a > std::min=5Felement which is probably what the author (I hope it wasn= 't > me...) was thinking of. Wow, I think you are exactly right. So could this have compiled all this time because operator< is valid for two iterators, which may be all the internals of std::min() would have needed=3F Looks like the code has been this way as far back as SVN goes, making it pre-open source LibMesh. -J |
From: Benjamin K. <ben...@na...> - 2008-01-23 16:20:41
|
>> Is that line of code even correct for Reals? std::min isn't supposed >> to operate on container iterators, it's just supposed to return the >> minimum of two elements with a defined operator<. There's a >> std::min_element which is probably what the author (I hope it wasn't >> me...) was thinking of. > > Wow, I think you are exactly right. So could this have compiled all > this time because operator< is valid for two iterators, which may be > all the internals of std::min() would have needed? Looks like the > code has been this way as far back as SVN goes, making it pre-open > source LibMesh. Then that excludes Roy as a suspect ;-) I'm sure it was me. -Ben |
From: Roy S. <roy...@ic...> - 2008-01-23 16:22:32
|
On Wed, 23 Jan 2008, John Peterson wrote: > Wow, I think you are exactly right. So could this have compiled all > this time because operator< is valid for two iterators, which may be > all the internals of std::min() would have needed? Looks like the > code has been this way as far back as SVN goes, making it pre-open > source LibMesh. Yuck. I guess nobody uses DistributedVector enough to have noticed the problem. The fix looks simple enough (we ought to be explicitly using std::complex<T>::real()), but I'm not sure of the cleanest way to do it in standard C++. You can't partially specialize one method or two in a templated class without redundantly declaring a specialized version of the whole class? Seriously? --- Roy |
From: Derek G. <fri...@gm...> - 2008-01-23 17:06:28
|
On Jan 23, 2008 9:22 AM, Roy Stogner <roy...@ic...> wrote: > The fix looks simple enough (we ought to be explicitly using > std::complex<T>::real()), but I'm not sure of the cleanest way to do > it in standard C++. You can't partially specialize one method or two > in a templated class without redundantly declaring a specialized > version of the whole class? Seriously? Sure you can... I do it with some of my classes in my code like this.... In something.h: template<class T> class Something { T doSomething(); }; template<> double Something<double>::doSomething(); template<> std::vector<double> Something<std::vector<double> >::doSomething(); Then in something.C: template<> double Something<double>::doSomething(){ stuff...; return double } template<> std::vector<double> Something<std::vector<double> >::doSomething() { stuff...; return std::vector<double> } Derek > --- > Roy > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Libmesh-devel mailing list > Lib...@li... > https://lists.sourceforge.net/lists/listinfo/libmesh-devel > |
From: Roy S. <roy...@ic...> - 2008-01-23 17:15:21
|
On Wed, 23 Jan 2008, Derek Gaston wrote: > Sure you can... I do it with some of my classes in my code like this.... > > In something.h: > > template<class T> > class Something > { > T doSomething(); > }; > > template<> > double Something<double>::doSomething(); The situation here's a little more complicated. This works: template<> Real DistributedVector<std::complex<double> >::min () const {...} This fails: template<typename T> Real DistributedVector<std::complex<T> >::min () const {...} with: error: invalid use of undefined type ‘class DistributedVector<std::complex<_Tp> >’ --- Roy |
From: Derek G. <fri...@gm...> - 2008-01-23 17:36:11
|
2008/1/23 Roy Stogner <roy...@ic...>: > template<typename T> > Real DistributedVector<std::complex<T> >::min () const {...} Have you tried: template<typename T> Real DistributedVector<template std::complex<T> >::min () const {...} Derek > > with: > > error: invalid use of undefined type 'class DistributedVector<std::complex<_Tp> >' > --- > Roy |
From: Roy S. <roy...@ic...> - 2008-01-23 18:02:48
|
On Wed, 23 Jan 2008, Derek Gaston wrote: > 2008/1/23 Roy Stogner <roy...@ic...>: >> template<typename T> >> Real DistributedVector<std::complex<T> >::min () const {...} > > Have you tried: > > template<typename T> > Real DistributedVector<template std::complex<T> >::min () const {...} No; I didn't even know that was valid syntax. Are you sure you don't mean: template<typename T> Real DistributedVector<typename std::complex<T> >::min () const {...} Adding "template" gives a bunch of "template argument 1 is invalid" errors; adding "typename" gives the same "invalid use of undefined type" errors. --- Roy |
From: Derek G. <fri...@gm...> - 2008-01-23 18:11:39
|
Well... I made up a little toy code here... and got several other people from around the office (who are _very_ knowledgeable in C++ lore) to come try and make it compile... with no luck. It just doesn't seem to be possible. I _did_ actually get it to compile with something like this: template<> void something<std::vector<class T> >::doSomething() {} But it fails to link if actually try to instantiate one of those things... so the code isn't getting generated correctly. At this point my advice is this: how many things is std::complex going to be templated on? I mean... really!?? Probably only just float, double, long double right? In reality, probably just double. My suggestion is just to do as you said earlier: template<> Real DistributedVector<std::complex<double> >::min () const {...} And if someone wants to use something besides double... then let them fill in the specialization.... Derek On Jan 23, 2008 11:02 AM, Roy Stogner <roy...@ic...> wrote: > > > On Wed, 23 Jan 2008, Derek Gaston wrote: > > > 2008/1/23 Roy Stogner <roy...@ic...>: > >> template<typename T> > >> Real DistributedVector<std::complex<T> >::min () const {...} > > > > Have you tried: > > > > template<typename T> > > Real DistributedVector<template std::complex<T> >::min () const {...} > > No; I didn't even know that was valid syntax. Are you sure you don't > mean: > > template<typename T> > Real DistributedVector<typename std::complex<T> >::min () const {...} > > Adding "template" gives a bunch of "template argument 1 is invalid" > errors; adding "typename" gives the same "invalid use of undefined > type" errors. > --- > Roy > |
From: Derek G. <fri...@gm...> - 2008-01-23 18:24:03
|
To expand on that you could even do something like: template<class T> void auxDoSomething() {} template<> void something<std::vector<double> >::doSomething() { auxDoSomething<double>(); } That way each of your specializations don't have to have code copied and pasted into them.... Derek On Jan 23, 2008 11:11 AM, Derek Gaston <fri...@gm...> wrote: > Well... I made up a little toy code here... and got several other > people from around the office (who are _very_ knowledgeable in C++ > lore) to come try and make it compile... with no luck. It just > doesn't seem to be possible. > > I _did_ actually get it to compile with something like this: > > template<> > void something<std::vector<class T> >::doSomething() > {} > > But it fails to link if actually try to instantiate one of those > things... so the code isn't getting generated correctly. > > At this point my advice is this: how many things is std::complex going > to be templated on? I mean... really!?? Probably only just float, > double, long double right? In reality, probably just double. My > suggestion is just to do as you said earlier: > > template<> > Real DistributedVector<std::complex<double> >::min () const {...} > > And if someone wants to use something besides double... then let them > fill in the specialization.... > > Derek > > > > > On Jan 23, 2008 11:02 AM, Roy Stogner <roy...@ic...> wrote: > > > > > > On Wed, 23 Jan 2008, Derek Gaston wrote: > > > > > 2008/1/23 Roy Stogner <roy...@ic...>: > > >> template<typename T> > > >> Real DistributedVector<std::complex<T> >::min () const {...} > > > > > > Have you tried: > > > > > > template<typename T> > > > Real DistributedVector<template std::complex<T> >::min () const {...} > > > > No; I didn't even know that was valid syntax. Are you sure you don't > > mean: > > > > template<typename T> > > Real DistributedVector<typename std::complex<T> >::min () const {...} > > > > Adding "template" gives a bunch of "template argument 1 is invalid" > > errors; adding "typename" gives the same "invalid use of undefined > > type" errors. > > --- > > Roy > > > |
From: John P. <pet...@cf...> - 2008-01-23 18:24:23
|
How about #ifdef USE_COMPLEX_NUMBERS // use ::real syntax #else #endif I didn't try this so if that makes no sense sorry. -J Derek Gaston writes: > Well... I made up a little toy code here... and got several other > people from around the office (who are _very_ knowledgeable in C++ > lore) to come try and make it compile... with no luck. It just > doesn't seem to be possible. > > I _did_ actually get it to compile with something like this: > > template<> > void something<std::vector<class T> >::doSomething() > {} > > But it fails to link if actually try to instantiate one of those > things... so the code isn't getting generated correctly. > > At this point my advice is this: how many things is std::complex going > to be templated on? I mean... really!?? Probably only just float, > double, long double right? In reality, probably just double. My > suggestion is just to do as you said earlier: > > template<> > Real DistributedVector<std::complex<double> >::min () const {...} > > And if someone wants to use something besides double... then let them > fill in the specialization.... > > Derek > > > > On Jan 23, 2008 11:02 AM, Roy Stogner <roy...@ic...> wrote: > > > > > > On Wed, 23 Jan 2008, Derek Gaston wrote: > > > > > 2008/1/23 Roy Stogner <roy...@ic...>: > > >> template<typename T> > > >> Real DistributedVector<std::complex<T> >::min () const {...} > > > > > > Have you tried: > > > > > > template<typename T> > > > Real DistributedVector<template std::complex<T> >::min () const {...} > > > > No; I didn't even know that was valid syntax. Are you sure you don't > > mean: > > > > template<typename T> > > Real DistributedVector<typename std::complex<T> >::min () const {...} > > > > Adding "template" gives a bunch of "template argument 1 is invalid" > > errors; adding "typename" gives the same "invalid use of undefined > > type" errors. > > --- > > Roy > > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Libmesh-devel mailing list > Lib...@li... > https://lists.sourceforge.net/lists/listinfo/libmesh-devel |
From: Roy S. <roy...@ic...> - 2008-01-23 18:49:10
|
On Wed, 23 Jan 2008, John Peterson wrote: > How about > > #ifdef USE_COMPLEX_NUMBERS > // use ::real syntax > #else > > #endif > > > I didn't try this so if that makes no sense sorry. That was actually the first thing I started coding, so hopefully it makes some sense. ;-) But DistributedVector is supposed to be templated, not just hard coded around Number, so I worried that we might see that break something later. So my current thought is just to make inline helper functions and do partial specialization on those, but for some reason now my compiler doesn't seem to recognize that Real min_realpart(const std::vector<std::complex<T> > &v) should take precedence (when it matches) over Real min_realpart(const std::vector<T> &v) It's just the exact same thing I did in parallel.h, but for some reason here it doesn't work? C++ just doesn't like me today. --- Roy |
From: Roy S. <roy...@ic...> - 2008-01-23 21:03:29
|
On Wed, 23 Jan 2008, Roy Stogner wrote: > Real min_realpart(const std::vector<T> &v) I finally realized that here was not the best place to bring in the template specialization. We've had some little-used functions libmesh_norm(x) (returning std::norm(x) or x*x as appropriate) and libmesh_real(x) (returning x.real() or x as appropriate) in one of the numerics headers, so now I've moved those to libmesh_common.h where we set Number=Real or Number=Complex, and I'm using them whereever possible. > It's just the exact same thing I did in parallel.h, but for some > reason here it doesn't work? C++ just doesn't like me today. What's really weird is that, while everything now compiles and links fine, I'm seeing this warning from distributed_vector.C and system_io.C: /home/roystgnr/libmesh/svn/include/parallel/parallel.h:64: warning: inline function ‘Parallel::data_type Parallel::datatype() [with T = std::complex<double>]’ used but never defined I have no idea what code is calling this (it's only used in other parallel.h functions, but any function called with a std::complex<T> is only supposed to be using the datatype of T, not of std::complex<T>. I also have no idea why it's linking correctly; if that function isn't defined in parallel.h it's certainly not defined anywhere else. Is the compiler trying to use a general template function, spitting out that warning, but then changing its mind and using the correct more specialized template function instead? I'm not even sure how to find out more other than to try Intel's compiler instead and see if it's more informative. Anyway, the SVN head should be working with --enable-complex now, but if you're using it, be paranoid and double-check your results in parallel. --- Roy |