Home > Net >  for loop not executing on zero parameters
for loop not executing on zero parameters

Time:03-21

I am a self-taught python & C programmer and Iam now trying to learn C

As a small exercise, I tried to port a function I had created in a Python minigame of mine, that generates a random matrix, then averages it, to create a map with terrain elevation.

I tried implementing it in C using a trick with size_t and the maximum size of an array, which I have already used successfully in C before.

However, the for-loop in my AverageSurroundings seems not to run when it is ran on row or column 0. This is confirmed by the output on stderr (I don't know how to put it in the question, sorry) and causes a division by zero error, which should not happen. I have done a small fix, but I can't find the origin of the problem

Here is a minimal snippet showing the problem.

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/assignment.hpp> //for <<= 
#include <cstdint>
#include <iostream>

static const std::size_t n_rows = 3;

static unsigned int
AverageSurroundings(const boost::numeric::ublas::matrix<unsigned int> mat,
                 const std::size_t row, const std::size_t col) {
  std::uint_fast16_t sum = 0; // <= 9*255= 2295 => 12 bits
  std::uint_fast8_t count = 0;
  std::cerr << "AverageSurroundings(" << row << ',' << col << ") called." << '\n';
  for ( std::size_t r = row - 1; r <= row   1; r  ) {
    for (std::size_t c = col - 1; c <= col   1; c  ) { // these values should remain positive, so we just 
                                                       // need to check if we are smaller than n_rows, 
                                                       //thanks to the wraparound of size_t.
      std::cerr<<"r:"<<r<<" c:"<<c<<'\n'; // FIXME : loop not executing on first row/column
      if (r < n_rows && c < n_rows) {
        sum  = mat(r, c);
        count  ;
        std::cerr << "AverageSurroundings(" << row << ',' << col << "): Neighbour found at (" << r<< ',' << c << ")." <<'\n';
      }
    }
  }
  std::cerr << std::endl; // flushing and adding a blank line.
  return count ? static_cast<unsigned int>(sum / count):0; //  count is 8bits long so no overflow is possible, casting to silence warning.
  //added ? to avoid floating point error for debug. FIXME : This should NOT BE 0   
}

static const boost::numeric::ublas::matrix<unsigned int>
Average(const boost::numeric::ublas::matrix<unsigned int> mat,
        const std::size_t rows) {
  using boost::numeric::ublas::matrix;
  matrix<unsigned int> m(n_rows, n_rows);
  for (std::size_t row = 0; row < rows; row  ) {
    for (std::size_t col = 0; col < rows; col  ) {
      m(row, col) = AverageSurroundings(mat, row, col);
      std::cout << m(row, col) << '\t';
    }
    std::cout << '\n';
  }
  std::cout << std::endl;
  return m;
}
int main() {
  using boost::numeric::ublas::matrix;
  matrix<unsigned int> m(n_rows,n_rows); m <<=  0, 1, 2,
                                                 3, 4, 5,
                                                 6, 7, 8;
  std::cout<< "---- RESULT ----" << '\n'; 
  const matrix<unsigned int> m2 = Average(m, n_rows);
}

and the corresponding output.

---- RESULT ----
0   0   0   
0   4   4   
0   5   6   

Any help on the issue and remarks or code formatting are welcome.

CodePudding user response:

You make a call to AverageSurroundings with row==0 and/or col==0 (see your loop variables in Average).

But std::size_t is an UNSIGNED type... So when it's zero, minus 1, it underflows in AverageSurroundings's loops and returns 0xFFFF FFFF FFFF FFFF... Which is obviously greater than row 1 (or col 1). So the loop isn't executed not a single time.

EDIT: Anyway, even without the underflow, you would still be outside your matrix, even with a proper "-1" as index...

  • Related