Double and Float based fundamental types (vectors, matrices, etc.) implemented side by side?

Started by
5 comments, last by Codarki 11 years, 9 months ago
Hi,

As I'm sure is standard practice, I have written a library to implement types like vectors, matrices, and so on, and it all works quite nicely. However I have hit a hurdle.

Using D3D9 for graphics, that seems to like having it's data in the form of single precision floats. Which is fair enough. But I'm feeling the need to do some intense physics simulation using double precision. So what I really want is some means of implementing both without duplicating my entire library.

My current implementation lets me switch between Float and Double types before compiling by means of a typedef instruction. But this doesn't quite give me the solution I need, as I'm stuck choosing one over the other.

[source lang="cpp"]// The library is called Util. Not a great name, I know. Here's a small excerpt
// from Util.h. Define DOUBLE before compiling to use the double type.
// Otherwise, use the float type.

#ifdef DOUBLE
typedef double Real;
#define NAMESPACE Maths::Double
#else
typedef float Real;
#define NAMESPACE Maths
#endif

namespace Util {
namespace NAMESPACE {
struct Angle; // Euler angle
struct Matrix; // 4x4 Matrix
struct Quaternion;
struct Vector3;
}
}

// An excerpt from Vector3.h

namespace util {
namespace NAMESPACE {
// Vector3, 3D coordinates
struct Vector3 {
public:
Real x, y, z;

Vector3(); // x=0 y=0 z=0
Vector3(Real); // x=a y=a z=a
Vector3(Real, Real, Real); // x=a y=b z=c
/// ... Etc.
};
}[/source]

Can anyone recommend a means to implement both types into the same library? Preferably while duplicating as little source code as possible.

I'm using Visual C++ 2010 Express. Thanks smile.png
Advertisement
How about using templates to achieve this? It's fast and easy, and you could even expand your vector class even further with other primitive types if you would ever need to do so.

I gets all your texture budgets!

As mentioned above, templates are just the right tool to use for your task.
In particular, class templates -- here's a tutorial with (plenty of) examples: http://cppannotations.sourceforge.net/cppannotations/html/cplusplus21.html#l451
Templates do seem like a nice solution, although I can't help but wonder whether it's a bit overkill, since there's only the two versions of each I need. :P Are there any other ways I could do this for comparison?
What's so overkill about it?
Basically, you replace 7 lines of code
[source lang="cpp"]
#ifdef DOUBLE
typedef double Real;
#define NAMESPACE Maths::Double
#else
typedef float Real;
#define NAMESPACE Maths
#endif
[/source]
with one* line of code
[source lang="cpp"]
template <typename Real>
[/source]
-- looks like less of an overkill to what it started as ;-)

* -- sure, you have to do that for each of { struct Angle; struct Matrix; struct Quaternion; struct Vector3; } -- that's still just 4 (< 7) lines of code, though :-)
And you don't need the separate-namespace-per-type complexity anymore, since, say Angle<float> and Angle<double> are unambiguously distinct types.

If for some reason you insist on the implementation that only lets you switch between floating-point types (and nothing else, refusing to compile for other kinds of types) you can easily achieve that with std::enable_if combined with std::is_floating_point:
http://en.cppreference.com/w/cpp/types/enable_if // see the "class A" example
http://en.cppreference.com/w/cpp/types/is_floating_point
I hadn't thought of it like that. I just assumed that templates came with a huge level of extra functionality which was going to waste.

I've done some experiments, and I think you're right. I really like how the template solution has worked out so far. I want to play around with it some more first, to better get to know it. But it's looking very likely that's the way I'll go!

Thank you for the help! :)
I'm using bunch of typedefs in addition to templates:

typedef vector<float,2> vector2f;
typedef vector<float,3> vector3f;
typedef vector<float,4> vector4f;
typedef vector<double,2> vector2d;
typedef vector<double,3> vector3d;
typedef vector<double,4> vector4d;

This topic is closed to new replies.

Advertisement