Sorry, something is wonky here. Everything past the code refuses to post so:
Taking points top to bottom covering a couple design items:
First, this is a vectorized 3D vector (I.e. SIMD instruction set for whatever CPU) which I hope is obvious. The only non-obvious is the 'v' postfix. I use a modification of Open GL naming convention, f means it is a single precision float and the v is a re-dedication of pointer to array 'v' to mean it is vectorized in this case. Not original, not outstanding, just easy and I like easy. 'k' for constants, old habit, probably could drop it. Case, same thing, old habit, like it though since using std and Math won't compile error on synonyms.
The first contentious item is the pair of converters. Construct from a SIMD type and convert to SIMD type and they are intentionally not explicit. I'm torn on this to a degree but in the long run I settled on non-explicit because I want to encourage passing things around as the fundamental type and not this light wrapper. Unlike most other conversion operations this one comes without a cost and more importantly passing by the fundamental type and not the wrapper is considerably more efficient in many ways. (Wait for the article for a discussion of this. ) I'm open to further discussion but if you are doing a SIMD library, you might as well encourage the efficient usage I believe.
The next contentious item is usually a pretty nasty one. Accessors for X, Y and Z, no direct access allowed. I don't do this for C++ class "purity" though, I'll drop kick purity in a heartbeat if I believe it is justified. Instead I use the accessors as a future preventative item for debugging. I can realistically argue that *every* game I've ever worked on has eventually had problems with NAN/INF getting into vectors and they were often nightmarish to track down and fix "because" of direct access to members which bypassed (yeah a purist point) the ability to add in debug code later to help track the problem. Getting used to 2 extra characters to type is trivial day to day, saving major time debugging is priceless to me.
Index operators. Errf.. This one has me torn. If I supply the normal index operator of '' the only way to do assignment is via returning a reference. I can/have coded up an intermediary object which can represent a reference into a SIMD vector element, but it is considerably more code (just lots of repeated boilerplate crap), not all that efficient and allows retention of the index object in ways very undesirable. Using the paren operator is a bit of a perversion of the syntax but in this way I can maintain the strict access control and not introduce the helper class to represent a reference. I could of course use standard '' for getter and '()' for the setter, but that struck me as wrong also. I'm very interested in comments about this. Of course it could be asked if this should exist at all, well kd-tree's, octree's, sweep and prune will all hate you if you don't supply it. Those are rather complicated systems which use axis indexing all over the place, not supporting index'd access is not an option in my opinion.
Set is just syntactic sugar for "X( x ); Y( y ); Z( z );". It avoids bugs in the cases you really do set all three members at the same time. No other reason for it's inclusion.
The dot product operator. Not sure how often this is argued but given it is a unique input and return type, and math texts use multiplication of scalars and vectors differently yet with the same symbol for 'multiply', I figure it is a good overload. I'm open to discussion.
Members, why so limited? Well, part of the intention is to be as clean as possible and not to present inconsistency in the supplied interface. So, why is magnitude a helper and not a member? Because all the members are currently limited to those which are non-const, return void, and need explicit access to the member data to perform their function. Magnitude (length) is just the square root of the vector dotted with itself so it is not a member function, just a syntactic helper to reduce typing. This may be taking minimalist to an extreme but it does present pretty solid consistency in all cases given that the helpers are all cases which can be computed with the minimal set of operations and no member access.
The static initializers. A case where I'm drop kicking all class purist thinking... The default constructor does *NOT* initialize to zero. I have reasons for this I'll explain in the article if you don't already know them. I keep rechecking the reasons for this every new compiler and it just keeps remaining true. I think of vectors as a fancy float anyway, so if I don't initialize it it is undefined, just like a float.
OK, that's some of the reasoning, hit me with yer best shot.
Edited by AllEightUp, 16 April 2013 - 11:49 PM.