[qvm] Terseness of syntax etc.

Adam Wulkiewicz wrote:
The formal review of Emil Dotchevski's QVM library begins today on 7th Dec and ends on 16th Dec. Full documentation is also viewable on Github: http://zajo.github.io/boost-qvm/
Following are some comments about the docs and syntax. This is based on an earlier look at the library when it was first announced and a quick look recently to see what has changed. I've not looked at the source code or tried to use the library. I wish that the docs started with a page showing how to use the library's built-in types. Currently, the first code that is presented shows how to define traits to make a user-supplied type work with the library. This is too advanced for the first page of the tutorial. The docs should start by showing how to do some high-school vector algebra using the built-in vector and matrix types. I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes. I had a quick think about how a struct with x,y,z members could be adapted. Am I right in thinking that it would be necessary to write accessors like this inside the traits specialisation: float ir(int i, xyz_vec const & v) { switch (i) { case 0: return v.x; case 1: return v.y; case 2: return v.z; } } ? If so, do we think that a compiler would successfully optimise that when it realised that x, y and z were in contiguous memory? (I guess you could also have an array of member pointers; would that work any better?) I'm really not a fan of the old operator% and now operator, syntax. To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ? I guess that what we'd really like to be able to do is to override operator. and write v.XY. There are proposals for adding operator. to the core language. Would those proposals support what is needed here? Actually, maybe this is closer to another proposal - the unified call syntax, which would make v.XY() equivalent to XY(v). I'll be interested to see what others think about these and other aspects of the proposal. Regards, Phil.

On Tue, Dec 8, 2015 at 11:25 AM, Phil Endecott
Adam Wulkiewicz wrote:
The formal review of Emil Dotchevski's QVM library begins today on 7th Dec and ends on 16th Dec. Full documentation is also viewable on Github: http://zajo.github.io/boost-qvm/
Following are some comments about the docs and syntax. This is based on an earlier look at the library when it was first announced and a quick look recently to see what has changed. I've not looked at the source code or tried to use the library.
I wish that the docs started with a page showing how to use the library's built-in types. Currently, the first code that is presented shows how to define traits to make a user-supplied type work with the library. This is too advanced for the first page of the tutorial. The docs should start by showing how to do some high-school vector algebra using the built-in vector and matrix types.
I found the documentation indeed poor in concrete/complete examples (and the unit tests don't help much).
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes.
I had a quick think about how a struct with x,y,z members could be adapted. Am I right in thinking that it would be necessary to write accessors like this inside the traits specialisation:
float ir(int i, xyz_vec const & v) { switch (i) { case 0: return v.x; case 1: return v.y; case 2: return v.z; } }
? If so, do we think that a compiler would successfully optimise that when it realised that x, y and z were in contiguous memory? (I guess you could also have an array of member pointers; would that work any better?)
There is also the function r, for which i is a template argument.
I'm really not a fan of the old operator% and now operator, syntax. To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
Plus, did I miss or there are no accessors with a dynamic index value? (I guess I missed it, because where ir as mentionned above).
I guess that what we'd really like to be able to do is to override operator. and write v.XY. There are proposals for adding operator. to the core language. Would those proposals support what is needed here? Actually, maybe this is closer to another proposal - the unified call syntax, which would make v.XY() equivalent to XY(v).
I'll be interested to see what others think about these and other aspects of the proposal. http://lists.boost.org/mailman/listinfo.cgi/boost
I totally agree with all you said. In addition, I would shy away from the X, Y, Z (and combinations) accessors using capital letters in order to avoid clashes with macros (I recently hit a clash with a struct member I named B0 and a macro in some Android system header; there is no B0 here, but I just want to illustrate the protential problem). -- François

On Tue, Dec 8, 2015 at 11:07 AM, Francois Duranleau < xiao.bai.xiong@gmail.com> wrote:
I totally agree with all you said. In addition, I would shy away from the X, Y, Z (and combinations) accessors using capital letters in order to avoid clashes with macros (I recently hit a clash with a struct member I named B0 and a macro in some Android system header; there is no B0 here, but I just want to illustrate the protential problem).
Swizzling is rendered nearly useless if it requires elaborate syntax or long names. Currently, if you want the Z and X swapped, you'd use (v,ZYX). I've considered using lower case but that doesn't work well in the case of (v,x) since it's quite likely that it'll clash with a local x. Clashes with macros are possible, but FWIW I've been using this library for years now and never had a clash (all these names are defined in a separate header, you don't have to include it if you don't need swizzling.) Thanks, Emil

On Tue, Dec 8, 2015 at 10:13 PM, Emil Dotchevski
On Tue, Dec 8, 2015 at 11:07 AM, Francois Duranleau < xiao.bai.xiong@gmail.com> wrote:
[... ] I would shy away from the X, Y, Z (and combinations) [...] to avoid clashes with macros
Swizzling is rendered nearly useless if it requires elaborate syntax or long names. Currently, if you want the Z and X swapped, you'd use (v,ZYX).
Again (and sorry for the bikeshedding), wouldn't (v,asZYX) or (v,toZYX) be terse enough and a bit more expressive, while further limiting potential conflicts with macros? --DD

On Wed, Dec 9, 2015 at 12:35 AM, Dominique Devienne
On Tue, Dec 8, 2015 at 10:13 PM, Emil Dotchevski
wrote: On Tue, Dec 8, 2015 at 11:07 AM, Francois Duranleau < xiao.bai.xiong@gmail.com> wrote:
[... ] I would shy away from the X, Y, Z (and combinations) [...] to avoid clashes with macros
Swizzling is rendered nearly useless if it requires elaborate syntax or long names. Currently, if you want the Z and X swapped, you'd use (v,ZYX).
Again (and sorry for the bikeshedding), wouldn't (v,asZYX) or (v,toZYX) be terse enough and a bit more expressive, while further limiting potential conflicts with macros? --DD
toZYX won't work because swizzling gives you an lvalue, e.g. you could write (v1,ZYX) += v2. asZYX could work but then (v,asZ) looks weird. If the swizzling names are to be prefixed with anything, then they should be converted to lowercase. The reason they use uppercase is so that single element access, e.g. (v,X) doesn't clash with single letter local variables which presumably are lower case. An important design goal of QVM is to provide quaternion, vector and matrix operations for user-defined types, which means that if you have a vector v, generally its elements could be defined in different ways, e.g. it could be something like struct float3 { float x, y, z; } or struct vec3 { float elements[3]; }. Regardless, (v,X) will access the X element of the vector. Using a longer name here just to avoid clashing with a macro X seems like a bad idea. Emil

Phil, thank you for your feedback. On Tue, Dec 8, 2015 at 8:25 AM, Phil Endecott < spam_from_boost_dev@chezphil.org> wrote:
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits.
I agree that transp is perhaps too short. The q_, v_ and m_traits though shouldn't be a problem since throughout the entire library q, v and m mean the same thing.
I had a quick think about how a struct with x,y,z members could be adapted. Am I right in thinking that it would be necessary to write accessors like this inside the traits specialisation:
float ir(int i, xyz_vec const & v) { switch (i) { case 0: return v.x; case 1: return v.y; case 2: return v.z; } }
The ir/iw accessors are for dynamic indexing and are generally optional. You use r and w for read and write access and in that case access to x, y and z can be implemented as specializations. I know, short names. :) So: struct float3 { float x,y,z; }; namespace boost { namespace qvm { template <class V> struct v_traits; template <> struct v_traitsre::float3 { typedef float scalar_type; static int const dim=3; template <int I> static float r( float3 const & ); template <int I> static float & w( float3 & ); }; template <> float v_traitsre::float3::r<0>( float3 const & a ) { return a.x; } template <> float v_traitsre::float3::r<1>( float3 const & a ) { return a.y; } template <> float v_traitsre::float3::r<2>( float3 const & a ) { return a.z; } template <> float & v_traitsre::float3::w<0>( float3 & a ) { return a.x; } template <> float & v_traitsre::float3::w<1>( float3 & a ) { return a.y; } template <> float & v_traitsre::float3::w<2>( float3 & a ) { return a.z; } } } I'm really not a fan of the old operator% and now operator, syntax.
To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
There is (m,A42) actually which seems preferable to element<4,2>(m). There is no good solution for swizzling, unfortunately. I ended up with comma because it looks nice to my eye, in combination with the parentheses. I can list several problems of choosing comma, much like I can for any other choice. :) Thanks, Emil http://www.revergestudios.com/reblog/index.php?n=ReCode

On Tue, Dec 8, 2015 at 9:53 PM, Emil Dotchevski
On Tue, Dec 8, 2015 at 8:25 AM, Phil Endecott < spam_from_boost_dev@chezphil.org> wrote:
I find most of the identifiers too short. You use r and w for read and write access [...]. I know, short names. :) template <int I> static float r( float3 const & ); template <int I> static float & w( float3 & );
Isn't the traditional get/set a good middle-ground between terseness and expressiveness? My $0.02. --DD template <int I> static float get( float3 const & );
template <int I> static float & set( float3 & );
template <> float v_traitsre::float3::get<0>( float3 const & a ) { return a.x; }

On Wed, Dec 9, 2015 at 12:31 AM, Dominique Devienne
On Tue, Dec 8, 2015 at 9:53 PM, Emil Dotchevski
wrote: On Tue, Dec 8, 2015 at 8:25 AM, Phil Endecott < spam_from_boost_dev@chezphil.org> wrote:
I find most of the identifiers too short. You use r and w for read and write access [...]. I know, short names. :) template <int I> static float r( float3 const & ); template <int I> static float & w( float3 & );
Isn't the traditional get/set a good middle-ground between terseness and expressiveness? My $0.02. --DD
It's not get/set semantics, it's read/write. Maybe I should call them read_access/write_access. Emil

Emil Dotchevski wrote:
I agree that transp is perhaps too short. The q_, v_ and m_traits though shouldn't be a problem since throughout the entire library q, v and m mean the same thing.
Throughout the entire *library*, yes; while you're writing your library I'm sure you don't get confused about what q, v and m stand for. But when they appear in my application, which pulls in maybe a dozen libraries, these short names are incomprehensible. Imagine the scenario where someone picks up some code written by someone else and needs to understand it: they really need to be able to read it without referring to the documentation for an obscure library first.
The ir/iw accessors are for dynamic indexing and are generally optional. You use r and w for read and write access and in that case access to x, y and z can be implemented as specializations.
Yes I'm aware of the template-index-parameter versions. But I was asking about those that take run-time index parameters. For example, consider a matrix-multiplication function; most likely that will use loops and invoke the ir/iw accessors. Have you looked at whether compilers produce respectable code in that case for structs with x,y,z elements?
I'm really not a fan of the old operator% and now operator, syntax. To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
There is (m,A42) actually which seems preferable to element<4,2>(m).
No, (m,A42) is not preferable to element<4,2>(m): - The (...,...) syntax doesn't look like a function invocation, it looks if anything like you're trying to form a row-vector with two elements. - "A" presumably is short for "at", saving one letter of typing at the expense of incomprehensibility. - "42" says forty-two, not 4,2.
There is no good solution for swizzling, unfortunately.
As an aside, I think it would be useful to present a motivation for the "swizzling" operations. I.e. a simple "real" example of why you might want to "swizzle". Also, I find the word "swizzle" a bit odd. To me it means the same as "munge" or "frobnicate" i.e. it's a nonsense-word that you use as a placeholder. I think what you're really doing is often a permutation, and could be named e.g. permuteZYX() - but there are other cases where you're duplicating or removing elements that aren't strictly permutations. Maybe there is some other mathematical term that encompasses that. Regards, Phil.

On 09.12.2015 15:23, Phil Endecott wrote:
Also, I find the word "swizzle" a bit odd.
FWIW it's a fairly established term in the computer graphics world, see for example https://www.opengl.org/wiki/Data_Type_(GLSL)#Swizzling - Asbjørn

On 12/9/2015 11:23 AM, Phil Endecott wrote:
Emil Dotchevski wrote:
There is no good solution for swizzling, unfortunately.
As an aside, I think it would be useful to present a motivation for the "swizzling" operations. I.e. a simple "real" example of why you might want to "swizzle".
Also, I find the word "swizzle" a bit odd. To me it means the same as "munge" or "frobnicate" i.e. it's a nonsense-word that you use as a placeholder. I think what you're really doing is often a permutation, and could be named e.g. permuteZYX() - but there are other cases where you're duplicating or removing elements that aren't strictly permutations. Maybe there is some other mathematical term that encompasses that.
"Swizzling" is how the operation is called in computer graphics, and that's the name people familiar with it will be looking for. Regards, -- Agustín K-ballo Bergé.- http://talesofcpp.fusionfenix.com

On Wed, Dec 9, 2015 at 8:23 AM, Phil Endecott < spam_from_boost_dev@chezphil.org> wrote:
Imagine the scenario where someone picks up some code written by someone else and needs to understand it: they really need to be able to read it without referring to the documentation for an obscure library first.
+1
As an aside, I think it would be useful to present a motivation for the "swizzling" operations. I.e. a simple "real" example of why you might want to "swizzle".
Because sometimes you need to. :) For instance, some graphics APIs lay out colors in RGBA order, others in ARGB, yet others in RBGA, etc. Many APIs do many or even all permutations.
Also, I find the word "swizzle" a bit odd.
It's a term of art that everyone who needs it already knows. It should not be changed. Zach

On 12/8/2015 1:25 PM, Phil Endecott wrote:
Adam Wulkiewicz wrote:
The formal review of Emil Dotchevski's QVM library begins today on 7th Dec and ends on 16th Dec. Full documentation is also viewable on Github: http://zajo.github.io/boost-qvm/
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes.
I used an earlier version of the library several years ago, back when it was called "Boost.LA", and I found extremely short identifiers to be a concern too. I could understand going for `mat` and `vec` instead of `matrix` and `vector`, but not just `m` and `v`. For pretty much every other identifier, I would like to see a full blown word instead.
I'm really not a fan of the old operator% and now operator, syntax. To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
The precedence issues are so bad with `operator,` that one has to pretty much always wrap it in parens, that makes all precedence issues go away. I think for that reason it's a better choice than `operator%`, that mostly just works and bit me over and over again. There are reasons against it too, for instance a missing include, a typo, a shadowing variable will turn a swizzling expression into a regular comma expression. That said, if I have to write `(v,XY)` instead of `v.XY` I'd rather write `XY(v)` instead.
I'll be interested to see what others think about these and other aspects of the proposal.
Regards, -- Agustín K-ballo Bergé.- http://talesofcpp.fusionfenix.com

On Wed, Dec 9, 2015 at 7:43 AM, Agustín K-ballo Bergé
On 12/8/2015 1:25 PM, Phil Endecott wrote:
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes.
I used an earlier version of the library several years ago, back when it was called "Boost.LA", and I found extremely short identifiers to be a concern too. I could understand going for `mat` and `vec` instead of `matrix` and `vector`, but not just `m` and `v`. For pretty much every other identifier, I would like to see a full blown word instead.
I'm really not a fan of the old operator% and now operator, syntax. To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
The precedence issues are so bad with `operator,` that one has to pretty much always wrap it in parens, that makes all precedence issues go away. I think for that reason it's a better choice than `operator%`, that mostly just works and bit me over and over again. There are reasons against it too, for instance a missing include, a typo, a shadowing variable will turn a swizzling expression into a regular comma expression.
That said, if I have to write `(v,XY)` instead of `v.XY` I'd rather write `XY(v)` instead.
I'll be interested to see what others think about these and other aspects of the proposal.
+1 to all of the above. -- François

On 12/8/2015 1:25 PM, Phil Endecott wrote:
Adam Wulkiewicz wrote:
The formal review of Emil Dotchevski's QVM library begins today on 7th Dec and ends on 16th Dec. Full documentation is also viewable on Github: http://zajo.github.io/boost-qvm/
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes.
I used an earlier version of the library several years ago, back when it was called "Boost.LA", and I found extremely short identifiers to be a concern too. I could understand going for `mat` and `vec` instead of `matrix` and `vector`, but not just `m` and `v`. For pretty much every other identifier, I would like to see a full blown word instead. I'm not sure we need the prefix nor the suffix. The operations shouldn't have the type on its name. If the operation depends on a concept (vector, matrix, quaternion) and
Le 09/12/2015 13:43, Agustín K-ballo Bergé a écrit :
the operation has no parameter of this type the function should have the
type as parameter
What would be wrong replacing
float vmag = mag(v);
float33 m = rotx_m<3>(3.14159f);
vref(v,YXZ) = rotx_m<3>(3.14159f) * v;
by
int mag = magnitude(v);
float33 m = rotate_x<M3>(3.14159f);
ref(v).YXZ() = rotate_x<M3>(3.14159f) * v;
Where M3 is a matrix with 3 rows, e.g.
using M3 = qvm::mat
I'm really not a fan of the old operator% and now operator, syntax. To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
The precedence issues are so bad with `operator,` that one has to pretty much always wrap it in parens, that makes all precedence issues go away. I think for that reason it's a better choice than `operator%`, that mostly just works and bit me over and over again. There are reasons against it too, for instance a missing include, a typo, a shadowing variable will turn a swizzling expression into a regular comma expression.
That said, if I have to write `(v,XY)` instead of `v.XY` I'd rather write `XY(v)` instead.
Clearly the operator, is too controversial. Isn't qvm::ref(v).XY() terse enough? Vicente P.S. ref result could depend on the associated traits of v and must use SFINAE

On Wed, Dec 9, 2015 at 3:41 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 09/12/2015 13:43, Agustín K-ballo Bergé a écrit :
On 12/8/2015 1:25 PM, Phil Endecott wrote:
Adam Wulkiewicz wrote:
The formal review of Emil Dotchevski's QVM library begins today on 7th Dec and ends on 16th Dec. Full documentation is also viewable on Github: http://zajo.github.io/boost-qvm/
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes.
I used an earlier version of the library several years ago, back when it was called "Boost.LA", and I found extremely short identifiers to be a concern too. I could understand going for `mat` and `vec` instead of `matrix` and `vector`, but not just `m` and `v`. For pretty much every other identifier, I would like to see a full blown word instead.
I'm not sure we need the prefix nor the suffix. The operations shouldn't have the type on its name. If the operation depends on a concept (vector, matrix, quaternion) and the operation has no parameter of this type the function should have the type as parameter
What would be wrong replacing
float vmag = mag(v); float33 m = rotx_m<3>(3.14159f); vref(v,YXZ) = rotx_m<3>(3.14159f) * v;
by
int mag = magnitude(v); float33 m = rotate_x<M3>(3.14159f); ref(v).YXZ() = rotate_x<M3>(3.14159f) * v;
Let me point out first that in this library q always means quaternion, m always means matrix, and v always means vector. With that in mind, could rotx_m<3> be misinterpreted? Secondly, the semantics of rotx_m are different from what you're imagining. It does *not* return a "proper" matrix object, it returns a reference to its argument reinterpreted as an unspecified non-copyable 3x3 matrix type, which essentially allows the passed angle (3.14159f) to participate as a 3x3 matrix in QVM operations without creating a temp. That's why when instantiating the rotx_m template you specify the dimensions but not the type of the matrix (of course you can assign the result to any compatible matrix type.) I'm really not a fan of the old operator% and now operator, syntax.
To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
The precedence issues are so bad with `operator,` that one has to pretty much always wrap it in parens, that makes all precedence issues go away. I think for that reason it's a better choice than `operator%`, that mostly just works and bit me over and over again. There are reasons against it too, for instance a missing include, a typo, a shadowing variable will turn a swizzling expression into a regular comma expression.
That said, if I have to write `(v,XY)` instead of `v.XY` I'd rather write `XY(v)` instead.
Clearly the operator, is too controversial.
Isn't
qvm::ref(v).XY()
terse enough?
Compared to (v,XY)? Emil

Le 10/12/2015 00:58, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 3:41 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 09/12/2015 13:43, Agustín K-ballo Bergé a écrit :
On 12/8/2015 1:25 PM, Phil Endecott wrote:
Adam Wulkiewicz wrote:
The formal review of Emil Dotchevski's QVM library begins today on 7th Dec and ends on 16th Dec. Full documentation is also viewable on Github: http://zajo.github.io/boost-qvm/
I find most of the identifiers too short. To give just a couple of examples: "transp" is used to mean "transpose". You save typing three letters, and get confusion with transparent, transport, etc. Then look at the names of some traits classes; elsewhere we have type_traits, allocator_traits, iterator_traits etc. all spelt out in full, but in qvm we have q_traits, v_traits and m_traits. I could go on but really almost every identifier is too short for my tastes.
I used an earlier version of the library several years ago, back when it was called "Boost.LA", and I found extremely short identifiers to be a concern too. I could understand going for `mat` and `vec` instead of `matrix` and `vector`, but not just `m` and `v`. For pretty much every other identifier, I would like to see a full blown word instead.
I'm not sure we need the prefix nor the suffix. The operations shouldn't have the type on its name. If the operation depends on a concept (vector, matrix, quaternion) and the operation has no parameter of this type the function should have the type as parameter
What would be wrong replacing
float vmag = mag(v); float33 m = rotx_m<3>(3.14159f); vref(v,YXZ) = rotx_m<3>(3.14159f) * v;
by
int mag = magnitude(v); float33 m = rotate_x<M3>(3.14159f); ref(v).YXZ() = rotate_x<M3>(3.14159f) * v;
Let me point out first that in this library q always means quaternion, m always means matrix, and v always means vector. With that in mind, could rotx_m<3> be misinterpreted?
Secondly, the semantics of rotx_m are different from what you're imagining. It does *not* return a "proper" matrix object, it returns a reference to its argument reinterpreted as an unspecified non-copyable 3x3 matrix type, which essentially allows the passed angle (3.14159f) to participate as a 3x3 matrix in QVM operations without creating a temp. That's why when instantiating the rotx_m template you specify the dimensions but not the type of the matrix (of course you can assign the result to any compatible matrix type.)
I'm really not a fan of the old operator% and now operator, syntax.
To me, (v,XY) looks like you're forming a row-vector with two elements. Is there a reason why these accessors can't be written with function syntax, i.e. XY(v) ? Or, for matrices, something like element<4,2>(m) rather than (m,A<4,2>) ?
The precedence issues are so bad with `operator,` that one has to pretty much always wrap it in parens, that makes all precedence issues go away. I think for that reason it's a better choice than `operator%`, that mostly just works and bit me over and over again. There are reasons against it too, for instance a missing include, a typo, a shadowing variable will turn a swizzling expression into a regular comma expression.
That said, if I have to write `(v,XY)` instead of `v.XY` I'd rather write `XY(v)` instead.
Clearly the operator, is too controversial.
Isn't
qvm::ref(v).XY()
terse enough?
Compared to (v,XY)?
The best is the enemy of the good. I requested if it is not terse enough. Vicente

On Wed, Dec 9, 2015 at 10:48 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:58, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 3:41 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Isn't
qvm::ref(v).XY()
terse enough?
Compared to (v,XY)?
The best is the enemy of the good.
I requested if it is not terse enough.
This problem does not have a good solution in C++, any chosen operator has drawbacks. That said, I wouldn't support ref(v).X() for accessing the X element of a vector, or ref(v).XY() for swizzling. Emil

On 10 December 2015 at 07:45, Emil Dotchevski
On Wed, Dec 9, 2015 at 10:48 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:58, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 3:41 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Isn't
qvm::ref(v).XY()
terse enough?
Compared to (v,XY)?
The best is the enemy of the good.
I requested if it is not terse enough.
This problem does not have a good solution in C++, any chosen operator has drawbacks. That said, I wouldn't support ref(v).X() for accessing the X element of a vector, or ref(v).XY() for swizzling.
what about ref(v)[xy]? wrapping the custom type in a ref call alleviates the restriction against the () and [] operators. or maybe: swizzle(v, xy) i also wonder if this might be possible: ref(v)->xy assuming the xy is a field in an enum that the operator-> returns. whether or not there's anyway of intercepting that to actually do the swizzle though i'm not sure...

On 10 December 2015 at 15:54, Sam Kellett
[snip]
This problem does not have a good solution in C++, any chosen operator has
drawbacks. That said, I wouldn't support ref(v).X() for accessing the X element of a vector, or ref(v).XY() for swizzling.
what about ref(v)[xy]? wrapping the custom type in a ref call alleviates the restriction against the () and [] operators.
or maybe: swizzle(v, xy)
i also wonder if this might be possible: ref(v)->xy assuming the xy is a field in an enum that the operator-> returns. whether or not there's anyway of intercepting that to actually do the swizzle though i'm not sure...
a couple more thoughts about this... what namespace is your comma operator in? it could be placed in an extra namespace which users can explicitly pull in if they prefer the super compact (albeit controversial) syntax and then anybody else could stick with a normal free function (like my swizzle(v, xy) above) which would be in the normal qvm namespace

On Thu, Dec 10, 2015 at 8:10 AM, Sam Kellett
what namespace is your comma operator in? it could be placed in an extra namespace which users can explicitly pull in if they prefer the super compact (albeit controversial) syntax and then anybody else could stick with a normal free function (like my swizzle(v, xy) above) which would be in the normal qvm namespace
Yes, all QVM names are safely defined in namespaces. It's usually fine to bring the entire qvm namespace into whatever namespace you want, though this includes both types and operations and it is possible to get ambiguities if you have another *type* by the same name, e.g. mat or vec. If that is a problem, you can bring in just boost::qvm::sfinae, which contains only operations. This should never lead to any ambiguities or clashes. Emil

On 10 December 2015 at 20:12, Emil Dotchevski
On Thu, Dec 10, 2015 at 8:10 AM, Sam Kellett
wrote: what namespace is your comma operator in? it could be placed in an extra namespace which users can explicitly pull in if they prefer the super compact (albeit controversial) syntax and then anybody else could stick with a normal free function (like my swizzle(v, xy) above) which would be in the normal qvm namespace
Yes, all QVM names are safely defined in namespaces.
It's usually fine to bring the entire qvm namespace into whatever namespace you want, though this includes both types and operations and it is possible to get ambiguities if you have another *type* by the same name, e.g. mat or vec.
If that is a problem, you can bring in just boost::qvm::sfinae, which contains only operations. This should never lead to any ambiguities or clashes.
well yes, but i mean the comma operator can go in an extra namespace so that by default it is not included with the others and if somebody wants to swizzle that way instead of using a free function that an explicitly 'using namespace boost::qvm::swizzle' to bring the comma operator into scope.

Le 10/12/2015 08:45, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 10:48 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/12/2015 00:58, Emil Dotchevski a écrit :
On Wed, Dec 9, 2015 at 3:41 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Isn't
qvm::ref(v).XY()
terse enough?
Compared to (v,XY)?
The best is the enemy of the good.
I requested if it is not terse enough.
This problem does not have a good solution in C++, any chosen operator has drawbacks. That said, I wouldn't support ref(v).X() for accessing the X element of a vector, or ref(v).XY() for swizzling.
Why? Vicente

On 10.12.2015 00:58, Emil Dotchevski wrote:
On Wed, Dec 9, 2015 at 3:41 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 09/12/2015 13:43, Agustín K-ballo Bergé a écrit :
That said, if I have to write `(v,XY)` instead of `v.XY` I'd rather write `XY(v)` instead.
Clearly the operator, is too controversial.
Isn't
qvm::ref(v).XY()
terse enough?
Compared to (v,XY)?
FWIW, there is precedent for using the "v.xyz" style for swizzling, though without the parenthesis behind. In OpenGL's shading language, GLSL[1], you can write v = w.xxyy; This would be equal to v = (w, XXYY); in current QVM syntax as I understand it. [1]: https://www.opengl.org/wiki/Data_Type_(GLSL)#Swizzling - Asbjørn

On 10 Dec 2015, at 11:43, Asbjørn
wrote: FWIW, there is precedent for using the "v.xyz" style for swizzling, though without the parenthesis behind. In OpenGL's shading language, GLSL[1], you can write
Same with HLSL and OpenCL: https://msdn.microsoft.com/en-us/library/windows/desktop/bb219869(v=vs.85).a... https://www.khronos.org/registry/cl/specs/ Thomas

On Thu, Dec 10, 2015 at 5:07 AM, Thomas Trummer
On 10 Dec 2015, at 11:43, Asbjørn
wrote: FWIW, there is precedent for using the "v.xyz" style for swizzling, though without the parenthesis behind. In OpenGL's shading language, GLSL[1], you can write
Same with HLSL and OpenCL:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb219869(v=vs.85).a... https://www.khronos.org/registry/cl/specs/
Indeed, however QVM can't use the dot syntax. So, the GLSL's v.xyz is (v,XYZ) in QVM. Thanks! Emil

On 10 Dec 2015, at 20:59, Emil Dotchevski
wrote: Indeed, however QVM can't use the dot syntax. So, the GLSL's v.xyz is (v,XYZ) in QVM.
That’s ok. I just wanted to provided further evidence that a) swizzling is a thing (despite it’s funny name) and b) it can be useful, and is in fact used, in certain similar domains. Thomas
participants (11)
-
Agustín K-ballo Bergé
-
Asbjørn
-
Dominique Devienne
-
Emil Dotchevski
-
Emil Dotchevski
-
Francois Duranleau
-
Phil Endecott
-
Sam Kellett
-
Thomas Trummer
-
Vicente J. Botet Escriba
-
Zach Laine