Subject: Re: [boost] [qvm] few q's for emil
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2011-07-18 17:55:27
On Mon, Jul 18, 2011 at 12:49 PM, Jeffrey Lee Hellrung, Jr.
> On Mon, Jul 18, 2011 at 12:21 PM, Emil Dotchevski
>> On Mon, Jul 18, 2011 at 11:14 AM, Jeffrey Lee Hellrung, Jr.
>> <jeffrey.hellrung_at_[hidden]> wrote:
>> > On Mon, Jul 18, 2011 at 12:24 AM, Emil Dotchevski
>> >> > as could proxy
>> >> > structures (c*v could be a proxy vector where w<0>(c*v) = 1 is
>> >> to
>> >> > w<0>(v) = 1/c).
>> >> This requirement means that none of the boost::qvm functions can
>> >> return temporary objects for proxies. The mutable proxies Boost QVM
>> >> avoid temporary objects by clever type casting. This helps control the
>> >> abstraction penalty of the library.
>> > I don't understand. Can you elaborate?
>> For example, here is the col_m function which maps a vector type A as
>> a matrix-column:
>> This technique avoids the creation of temporaries which are often the
>> source of abstraction penalties.
> Wow, I guess I'm surprised the temporaries wouldn't be optimized away, at
> least in this case...
It is likely that they'll be optimized away, but in my experience
temporaries are more likely to confuse optimizers than inline
functions. Not that I have hard data to back this claim. :)
> I understand your desire to play it safe for now and require lvalue
> references for w. However, I don't see how the above example precludes the
> use of proxy references :/ Sorry for being dense. I would think col_m_<A>
> would simply use whatever reference type (lvalue or proxy) that A uses...
> In any case, I can't really think of a compelling use case for proxy
> references yet (can you?), so it's not a huge deal.
No you're right, allowing for more generic ::w would not preclude
this, I was just pointing out that I've tried to keep things
straight-forward. This doesn't mean that I'm against it in principle,
but ideally I'd like to examine several use cases that require this
complication in order to come up with the correct more generic formal
>>> > Why do you require the dimension of vectors (and, likely, matrices; I
>> >> > haven't checked) to be strictly greater than 0? Sometimes a
>> >> 0-dimensional
>> >> > vector is convenient to have when writing dimension-independent code.
>> >> I wasn't aware of that. What can you do with a zero dimensional vector?
>> > Not much, to be sure (all zero-dim vectors of a given scalar type, at
>> > would be equal). I can't give a concrete example at the moment, but I
>> > to remember some recursion on dimension I've done where the base case was
>> > simpler to express at 0 than at 1.
>> In principle I'm not against lifting this requirement, but I want to
>> make sure it's needed first. Doesn't this only affect the
>> specialization of v_traits? I mean, you can still write recursive
>> template meta programs that use zero as the base case as long as they
>> don't define zero size in a v_traits specialization.
> Again, this is still kind of pure speculation. I could imagine an algorithm
> written using the QVM abstraction which, say, recurses in dimension by
> (lazily) removing the first or last element of vectors (does QVM support
> such operations?), and at some point you'd remove the first or last element
> of a 1-vector. But it's fair to avoid lifting the requirement until
> needed. I was just wondering if there was some other rationale for
> requiring a positive dimension other than "I hadn't seen a need for it".
Right, I try to avoid speculations like this. It is important to
understand the use cases before designing an interface to support
To answer your question, there aren't currently functions to remove an
element of a vector except as part of the swizzling support which can
only output dimensions up to 4. For example v%YZ maps the Y and Z
elements of a vector with size at least 3, as a 2D vector. There are
functions for removing rows and columns of matrices, so perhaps a
similar functionality makes sense for vectors in general.
>> No I have not. The determinant computations are currently pretty
>> straight-forward, save the use of an off-line code generator.
> I just ran through a quick count of the number of multiplies, and for 4x4
> matrices, dynamic programming will reduce the number of multiplications from
> 40 to 28 over straightforward recursion, while for 5x5 matrices, the
> reduction from 205 to 75 (or so).
I welcome any optimization like this. Is it possible to write a
generic code generator for this algorithm, similarly to the other code
generators in libs/qvm/gen/gen.cpp?
>> >> I guess that the documentation isn't clear but boost/qvm/math.hpp
>> >> defines function templates that correspond to the functions from
>> >> <math.h>. The templates are specialized for float and double, but can
>> >> be specialized for any other scalar. That said, I don't have tests
>> >> using any other scalar type. Perhaps a fixed point scalar should be
>> >> implemented to make sure there isn't something missing.
>> > Are complex scalar types within the scope of the library?
>> I think so. I've certainly been very careful to design a type system
>> that permits non-trivial scalar types.
> I figured complex scalars might be tacitly supported, as you don't require
> ordering comparisons on scalar types, but I'm not sure the scalar type
> requirements you give are sufficient (e.g., you probably need conjugation
> somehow). In any case, this was more of a curiosity than an actual need.
Like I said, my motivation was to write a generic library that's
useful for 3D graphics, but I'm not against extending the scope beyond
that as long as things don't get too crazy. Complex and fixed point
scalars seem appropriate, but I know I don't want to support vectors
and matrices of dynamic size or general sparsity.
> I'll continue to browse through the library and let you know if I have
> additional comments or questions.
I appreciate your feedback!
Reverge Studios, Inc.