Jump to content
  • Advertisement
Sign in to follow this  
l0calh05t

Compiler bug?

This topic is 3985 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, having had my problems with *one* compiler bug (the compiler is VC++ 2005) yesterday (Which has apparently been solved by Microsoft, but the solution was only released with VS2008...), I seem to have found another one, but maybe I'm just overlooking something stupid I did... I have the following class (most stuff removed)
template<unsigned int N, unsigned int M, typename Scalar>
class mat
	: boost::additive< mat<N,M,Scalar>
	, boost::multiplicative2< mat<N,M,Scalar>, Scalar
	, boost::equality_comparable< mat<N,M,Scalar>
	> > >
{
public:
 /*...*/

 const vec<N,Scalar>& column(unsigned int j) const
 {
  assert(j < M);
  return *(reinterpret_cast<const vec<N,Scalar>* >(&data[N*j]));
 }

 vec<N,Scalar>& column(unsigned int j)
 {
  assert(j < M);
  return *(reinterpret_cast<vec<N,Scalar>* >(&data[N*j]));
 }

 /*...*/

private:
 Scalar data[N*M]; // In column-major storage
};


and of course a corresponding vector class with all the usual operators etc. The following code (for computing a determinant) fails:
template<unsigned int N, typename Scalar, bool cond>
class det
{
public:
 /* Gaussian elimination for large matrices */
 static Scalar compute(const mat<N,N,Scalar>& a)
 {
  mat<N,N,Scalar> copy = a; /* Is it ok to allocate this on the stack? */
  Scalar factor = 1;
  unsigned int i = 0;
  unsigned int j = 0;

  while(i < N && j < N)
  {
   cout << copy << endl;
   unsigned int maxj = j;
   for(unsigned int k = j+1; k < N; ++k)
   {
    if(std::abs(copy(i,k)) > std::abs(copy(i,maxj)))
     maxj = k;
   }
   if(copy(i,maxj) != 0)
   {
    /* Swap columns j and maxj */
    vec<N,Scalar> temp = copy.column(j);
    copy.column(j) = copy.column(maxj);
    copy.column(maxj) = temp;

    cout << "Swapped " << copy << endl;

    if(j != maxj)
     factor = -factor * copy(i,j);
    else
     factor = factor * copy(i,j);

    copy.column(j) /= copy(i,j); /* why doesn't this work?? (only copy(i,j) is being updated) */
    // copy.column(j) = copy.column(j) / copy(i,j); /* this on the other hand works */

    cout << "Divided " << copy << endl;

    for(unsigned int k = j+1; k < N; ++k)
     copy.column(k) -= copy(i,k) * copy.column(j);

    ++i;
   }
   else /* Early out */
   {
    cout << "Early out" << endl;
    return 0;
   }
   ++j;
  }

  return factor;
 }
};


Share this post


Link to post
Share on other sites
Advertisement
What do you mean by "The following code ... fails"?

Does it fail to compile? If so, what error message does the compiler give?
Does it crash at runtime? Is so, what error message do you get?
Does it fail to printthe correct results? If so, what does it print?

Share this post


Link to post
Share on other sites
I didn't mention it explicitly because it is already in the comments:


/*...*/
copy.column(j) /= copy(i,j); /* why doesn't this work?? (only copy(i,j) is being updated) */
// copy.column(j) = copy.column(j) / copy(i,j); /* this on the other hand works */
/*...*/



1. no, it does not fail to compile
2. no, it does not crash at runtime
3. the results are incorrect, since only the element corresponding to copy(i,j) in copy.column(j) is really divided, the others are not.

Share this post


Link to post
Share on other sites
    copy.column(j) /= copy(i,j);

and
    copy.column(j) = copy.column(j) / copy(i,j);

use two different operators... I suspect they are overloaded in the vec class? The /= operator might not implemented properly (or not at all?).

Share this post


Link to post
Share on other sites
no, technically they use the same (i use boost::multiplicative2 for vec as well, which just creates a temporary vec, applies /= to the temporary vec and returns the temporary)

and it is defined as:


vec& operator/= (const Scalar& s)
{
for(unsigned int i = 0; i < N; ++i)
data /= s;
return *this;
}



Which is absolutely, 100%ly correct. (and it works everywhere else)

Share this post


Link to post
Share on other sites
fun fact:

if N is 4 and Scalar is float it works with both.
the only difference:
vec<4,float> is specialized and uses sse (which is what causes the other compiler bug to occur, although luckily only in debug builds), otherwise it is identical

and if i deactivate SSE (via a define), vec<4,float> operator /= is identical to the non-specialized version (the only difference are named accessors, and swizzle ops which are not used at that point), it *also* works

Share this post


Link to post
Share on other sites
Quote:
Original post by l0calh05t
never mind... i found the error. so this one is not a compiler bug...

Most of the time it is not the compiler.

Share this post


Link to post
Share on other sites
When you get really stuck on what seems to be (in your mind) a compiler bug, make a test case. That is, a MINIMAL piece of code that exhibits the problem. Usually in the process of doing so, you find the problem, if not, you allow other people to help understand the problem better to help you. If you haven't done that, you can't really blame the compiler yet. MSVC does have bugs though.

Share this post


Link to post
Share on other sites
Quote:
Original post by Crypter
Most of the time it is not the compiler.


Which is exactly why I asked here...

And yeah, VS has got some bugs, for example the one I encountered earlier (VS was misaligning an __m128 variable on the stack, but it only occurs in debug mode with inline template functions... very strange...)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!