<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "metadata/ColorFilterArray.h"
#include "common/Common.h"                // for writeLog, DEBUG_PRIO::EXTRA
#include "common/Point.h"                 // for iPoint2D, iPoint2D::value_...
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include <algorithm>                      // for fill
#include <cinttypes>                      // for PRId64
#include <cstdarg>                        // for va_arg, va_end, va_list
#include <cstdlib>                        // for size_t, abs
#include <map>                            // for map
#include <stdexcept>                      // for out_of_range
#include <string>                         // for string

using std::vector;

using std::out_of_range;
using std::map;

namespace rawspeed {

ColorFilterArray::ColorFilterArray(const iPoint2D &_size) {
  setSize(_size);
}

void ColorFilterArray::setSize(const iPoint2D& _size)
{
  size = _size;

  if (size.area() > 36) {
    // Bayer, FC() supports 2x8 pattern
    // X-Trans is 6x6 pattern
    // is there anything bigger?
    ThrowRDE("if your CFA pattern is really %" PRId64 " pixels "
             "in area we may as well give up now",
             size.area());
  }
  if (size.area() <= 0)
    return;
  cfa.resize(size.area());
  fill(cfa.begin(), cfa.end(), CFAColor::UNKNOWN);
}

CFAColor ColorFilterArray::getColorAt( int x, int y ) const
{
  if (cfa.empty())
    ThrowRDE("No CFA size set");

  // calculate the positive modulo [0 .. size-1]
  x = (x % size.x + size.x) % size.x;
  y = (y % size.y + size.y) % size.y;

  return cfa[x + static_cast<size_t>(y) * size.x];
}

void ColorFilterArray::setCFA( iPoint2D in_size, ... )
{
  if (in_size != size) {
    setSize(in_size);
  }
  va_list arguments;
  va_start(arguments, in_size);
  for (auto i = 0UL; i < size.area(); i++) {
    cfa[i] = static_cast<CFAColor>(va_arg(arguments, int));
  }
  va_end (arguments);
}

void ColorFilterArray::shiftRight(int n) {
  if (cfa.empty())
    ThrowRDE("No CFA size set (or set to zero)");

  writeLog(DEBUG_PRIO::EXTRA, "Shift right:%d", n);
  n %= size.x;
  if (n == 0)
    return;

  vector<CFAColor> tmp(size.area());
  for (int y = 0; y < size.y; ++y) {
    for (int x = 0; x < size.x; ++x) {
      tmp[x + static_cast<size_t>(y) * size.x] = getColorAt(x + n, y);
    }
  }
  cfa = tmp;
}

void ColorFilterArray::shiftDown(int n) {
  if (cfa.empty())
    ThrowRDE("No CFA size set (or set to zero)");

  writeLog(DEBUG_PRIO::EXTRA, "Shift down:%d", n);
  n %= size.y;
  if (n == 0)
    return;

  vector<CFAColor> tmp(size.area());
  for (int y = 0; y < size.y; ++y) {
    for (int x = 0; x < size.x; ++x) {
      tmp[x + static_cast<size_t>(y) * size.x] = getColorAt(x, y + n);
    }
  }
  cfa = tmp;
}

std::string ColorFilterArray::asString() const {
  std::string dst;
  for (int y = 0; y < size.y; y++) {
    for (int x = 0; x < size.x; x++) {
      dst += colorToString(getColorAt(x,y));
      dst += (x == size.x - 1) ? "\n" : ",";
    }
  }
  return dst;
}

uint32_t ColorFilterArray::shiftDcrawFilter(uint32_t filter, int x, int y) {
  // filter is a series of 4 bytes that describe a 2x8 matrix. 2 is the width,
  // 8 is the height. each byte describes a 2x2 pixel block. so each pixel has
  // 2 bits of information. This allows to distinguish 4 different colors.

  if (std::abs(x) & 1) {
    // A shift in x direction means swapping the first and second half of each
    // nibble.
    // see http://graphics.stanford.edu/~seander/bithacks.html#SwappingBitsXOR
    for (int n = 0; n < 8; ++n) {
      int i = n * 4;
      int j = i + 2;
      uint32_t t = ((filter >> i) ^ (filter >> j)) & ((1U << 2) - 1);
      filter = filter ^ ((t << i) | (t << j));
    }
  }

  if (y == 0)
    return filter;

  // A shift in y direction means rotating the whole int by 4 bits.
  y *= 4;
  y = y >= 0 ? y % 32 : 32 - ((-y) % 32);
  if (y != 0)
    filter = (filter >> y) | (filter << (32 - y));

  return filter;
}

const map<CFAColor, std::string> ColorFilterArray::color2String = {
    {CFAColor::RED, "RED"},         {CFAColor::GREEN, "GREEN"},
    {CFAColor::BLUE, "BLUE"},       {CFAColor::CYAN, "CYAN"},
    {CFAColor::MAGENTA, "MAGENTA"}, {CFAColor::YELLOW, "YELLOW"},
    {CFAColor::WHITE, "WHITE"},     {CFAColor::FUJI_GREEN, "FUJIGREEN"},
    {CFAColor::UNKNOWN, "UNKNOWN"}};

std::string ColorFilterArray::colorToString(CFAColor c) {
  try {
    return color2String.at(c);
  } catch (const std::out_of_range&) {
    ThrowRDE("Unsupported CFA Color: %u", static_cast<unsigned>(c));
  }
}

void ColorFilterArray::setColorAt(iPoint2D pos, CFAColor c) {
  if (pos.x >= size.x || pos.x < 0)
    ThrowRDE("position out of CFA pattern");
  if (pos.y >= size.y || pos.y < 0)
    ThrowRDE("position out of CFA pattern");
  cfa[pos.x + static_cast<size_t>(pos.y) * size.x] = c;
}

static uint32_t toDcrawColor(CFAColor c) {
  switch (c) {
  case CFAColor::FUJI_GREEN:
  case CFAColor::RED:
    return 0;
  case CFAColor::MAGENTA:
  case CFAColor::GREEN:
    return 1;
  case CFAColor::CYAN:
  case CFAColor::BLUE:
    return 2;
  case CFAColor::YELLOW:
    return 3;
  default:
    throw out_of_range(ColorFilterArray::colorToString(c));
  }
}

uint32_t ColorFilterArray::getDcrawFilter() const {
  //dcraw magic
  if (size.x == 6 && size.y == 6)
    return 9;

  if (cfa.empty() || size.x > 2 || size.y > 8 || !isPowerOfTwo(size.y))
    return 1;

  uint32_t ret = 0;
  for (int x = 0; x < 2; x++) {
    for (int y = 0; y < 8; y++) {
      uint32_t c = toDcrawColor(getColorAt(x, y));
      int g = (x >> 1) * 8;
      ret |= c << ((x&1)*2 + y*4 + g);
    }
  }

  writeLog(DEBUG_PRIO::EXTRA, "%s", asString().c_str());
  writeLog(DEBUG_PRIO::EXTRA, "DCRAW filter:%x", ret);

  return ret;
}

} // namespace rawspeed
<commit_msg>`ColorFilterArray::setSize()`: require either zero size, or positive size<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "metadata/ColorFilterArray.h"
#include "common/Common.h"                // for writeLog, DEBUG_PRIO::EXTRA
#include "common/Point.h"                 // for iPoint2D, iPoint2D::value_...
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include <algorithm>                      // for fill
#include <cinttypes>                      // for PRId64
#include <cstdarg>                        // for va_arg, va_end, va_list
#include <cstdlib>                        // for size_t, abs
#include <map>                            // for map
#include <stdexcept>                      // for out_of_range
#include <string>                         // for string

using std::vector;

using std::out_of_range;
using std::map;

namespace rawspeed {

ColorFilterArray::ColorFilterArray(const iPoint2D &_size) {
  setSize(_size);
}

void ColorFilterArray::setSize(const iPoint2D& _size)
{
  if (_size == iPoint2D(0, 0))
    return;

  assert(_size.hasPositiveArea() && "CFA must have positive size.");

  size = _size;

  if (size.area() > 36) {
    // Bayer, FC() supports 2x8 pattern
    // X-Trans is 6x6 pattern
    // is there anything bigger?
    ThrowRDE("if your CFA pattern is really %" PRId64 " pixels "
             "in area we may as well give up now",
             size.area());
  }
  if (size.area() <= 0)
    return;
  cfa.resize(size.area());
  fill(cfa.begin(), cfa.end(), CFAColor::UNKNOWN);
}

CFAColor ColorFilterArray::getColorAt( int x, int y ) const
{
  if (cfa.empty())
    ThrowRDE("No CFA size set");

  // calculate the positive modulo [0 .. size-1]
  x = (x % size.x + size.x) % size.x;
  y = (y % size.y + size.y) % size.y;

  return cfa[x + static_cast<size_t>(y) * size.x];
}

void ColorFilterArray::setCFA( iPoint2D in_size, ... )
{
  if (in_size != size) {
    setSize(in_size);
  }
  va_list arguments;
  va_start(arguments, in_size);
  for (auto i = 0UL; i < size.area(); i++) {
    cfa[i] = static_cast<CFAColor>(va_arg(arguments, int));
  }
  va_end (arguments);
}

void ColorFilterArray::shiftRight(int n) {
  if (cfa.empty())
    ThrowRDE("No CFA size set (or set to zero)");

  writeLog(DEBUG_PRIO::EXTRA, "Shift right:%d", n);
  n %= size.x;
  if (n == 0)
    return;

  vector<CFAColor> tmp(size.area());
  for (int y = 0; y < size.y; ++y) {
    for (int x = 0; x < size.x; ++x) {
      tmp[x + static_cast<size_t>(y) * size.x] = getColorAt(x + n, y);
    }
  }
  cfa = tmp;
}

void ColorFilterArray::shiftDown(int n) {
  if (cfa.empty())
    ThrowRDE("No CFA size set (or set to zero)");

  writeLog(DEBUG_PRIO::EXTRA, "Shift down:%d", n);
  n %= size.y;
  if (n == 0)
    return;

  vector<CFAColor> tmp(size.area());
  for (int y = 0; y < size.y; ++y) {
    for (int x = 0; x < size.x; ++x) {
      tmp[x + static_cast<size_t>(y) * size.x] = getColorAt(x, y + n);
    }
  }
  cfa = tmp;
}

std::string ColorFilterArray::asString() const {
  std::string dst;
  for (int y = 0; y < size.y; y++) {
    for (int x = 0; x < size.x; x++) {
      dst += colorToString(getColorAt(x,y));
      dst += (x == size.x - 1) ? "\n" : ",";
    }
  }
  return dst;
}

uint32_t ColorFilterArray::shiftDcrawFilter(uint32_t filter, int x, int y) {
  // filter is a series of 4 bytes that describe a 2x8 matrix. 2 is the width,
  // 8 is the height. each byte describes a 2x2 pixel block. so each pixel has
  // 2 bits of information. This allows to distinguish 4 different colors.

  if (std::abs(x) & 1) {
    // A shift in x direction means swapping the first and second half of each
    // nibble.
    // see http://graphics.stanford.edu/~seander/bithacks.html#SwappingBitsXOR
    for (int n = 0; n < 8; ++n) {
      int i = n * 4;
      int j = i + 2;
      uint32_t t = ((filter >> i) ^ (filter >> j)) & ((1U << 2) - 1);
      filter = filter ^ ((t << i) | (t << j));
    }
  }

  if (y == 0)
    return filter;

  // A shift in y direction means rotating the whole int by 4 bits.
  y *= 4;
  y = y >= 0 ? y % 32 : 32 - ((-y) % 32);
  if (y != 0)
    filter = (filter >> y) | (filter << (32 - y));

  return filter;
}

const map<CFAColor, std::string> ColorFilterArray::color2String = {
    {CFAColor::RED, "RED"},         {CFAColor::GREEN, "GREEN"},
    {CFAColor::BLUE, "BLUE"},       {CFAColor::CYAN, "CYAN"},
    {CFAColor::MAGENTA, "MAGENTA"}, {CFAColor::YELLOW, "YELLOW"},
    {CFAColor::WHITE, "WHITE"},     {CFAColor::FUJI_GREEN, "FUJIGREEN"},
    {CFAColor::UNKNOWN, "UNKNOWN"}};

std::string ColorFilterArray::colorToString(CFAColor c) {
  try {
    return color2String.at(c);
  } catch (const std::out_of_range&) {
    ThrowRDE("Unsupported CFA Color: %u", static_cast<unsigned>(c));
  }
}

void ColorFilterArray::setColorAt(iPoint2D pos, CFAColor c) {
  if (pos.x >= size.x || pos.x < 0)
    ThrowRDE("position out of CFA pattern");
  if (pos.y >= size.y || pos.y < 0)
    ThrowRDE("position out of CFA pattern");
  cfa[pos.x + static_cast<size_t>(pos.y) * size.x] = c;
}

static uint32_t toDcrawColor(CFAColor c) {
  switch (c) {
  case CFAColor::FUJI_GREEN:
  case CFAColor::RED:
    return 0;
  case CFAColor::MAGENTA:
  case CFAColor::GREEN:
    return 1;
  case CFAColor::CYAN:
  case CFAColor::BLUE:
    return 2;
  case CFAColor::YELLOW:
    return 3;
  default:
    throw out_of_range(ColorFilterArray::colorToString(c));
  }
}

uint32_t ColorFilterArray::getDcrawFilter() const {
  //dcraw magic
  if (size.x == 6 && size.y == 6)
    return 9;

  if (cfa.empty() || size.x > 2 || size.y > 8 || !isPowerOfTwo(size.y))
    return 1;

  uint32_t ret = 0;
  for (int x = 0; x < 2; x++) {
    for (int y = 0; y < 8; y++) {
      uint32_t c = toDcrawColor(getColorAt(x, y));
      int g = (x >> 1) * 8;
      ret |= c << ((x&1)*2 + y*4 + g);
    }
  }

  writeLog(DEBUG_PRIO::EXTRA, "%s", asString().c_str());
  writeLog(DEBUG_PRIO::EXTRA, "DCRAW filter:%x", ret);

  return ret;
}

} // namespace rawspeed
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for files.c
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "Basics/StringBuffer.h"
#include "BasicsC/files.h"

using namespace triagens::basics;

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CFilesSetup {
  CFilesSetup () : _directory(TRI_UNKNOWN_MEM_ZONE) {
    BOOST_TEST_MESSAGE("setup files");

    _directory.appendText("/tmp/arangotest-");
    _directory.appendInteger((uint64_t) TRI_microtime());

    TRI_CreateDirectory(_directory.c_str());
  }

  ~CFilesSetup () {
    BOOST_TEST_MESSAGE("tear-down files");

    // let's be sure we delete the right stuff
    assert(_directory.length() > 10);
    assert(memcmp((void*) _directory.c_str(), (void*) "/tmp/arangotest-", 16) == 0);

    TRI_RemoveDirectory(_directory.c_str());
  }

  StringBuffer* writeFile (const char* blob) {
    static uint64_t counter = 0;

    StringBuffer* filename = new StringBuffer(TRI_UNKNOWN_MEM_ZONE);
    filename->appendText(_directory);
    filename->appendText("/tmp-");
    filename->appendInteger(++counter);

    int fd = TRI_OPEN(filename->c_str(), O_RDWR | O_CREAT);

    if (fd) {
      ::write(fd, &blob, strlen(blob));
      ::close(fd);
    }
    else {
      BOOST_CHECK_EQUAL(false, true);
    }

    return filename;
  }

  StringBuffer _directory;
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CFilesTest, CFilesSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test file exists
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_existsfile) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(true, TRI_ExistsFile(filename->c_str()));
  TRI_UnlinkFile(filename->c_str());

  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size empty file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_empty) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(0, (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_exists) {
  const char* buffer = "the quick brown fox";

  StringBuffer* filename = writeFile(buffer);
  BOOST_CHECK_EQUAL(strlen(buffer), (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size, non existing file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_non) {
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("h5uuuuui3unn645wejhdjhikjdsf"));
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("dihnui8ngiu54"));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<commit_msg>fixed uninitialised bytes in call to write<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for files.c
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include <boost/test/unit_test.hpp>

#include "Basics/StringBuffer.h"
#include "BasicsC/files.h"

using namespace triagens::basics;

// -----------------------------------------------------------------------------
// --SECTION--                                                 setup / tear-down
// -----------------------------------------------------------------------------

struct CFilesSetup {
  CFilesSetup () : _directory(TRI_UNKNOWN_MEM_ZONE) {
    BOOST_TEST_MESSAGE("setup files");

    _directory.appendText("/tmp/arangotest-");
    _directory.appendInteger((uint64_t) TRI_microtime());

    TRI_CreateDirectory(_directory.c_str());
  }

  ~CFilesSetup () {
    BOOST_TEST_MESSAGE("tear-down files");

    // let's be sure we delete the right stuff
    assert(_directory.length() > 10);
    assert(memcmp((void*) _directory.c_str(), (void*) "/tmp/arangotest-", 16) == 0);

    TRI_RemoveDirectory(_directory.c_str());
  }

  StringBuffer* writeFile (const char* blob) {
    static uint64_t counter = 0;

    StringBuffer* filename = new StringBuffer(TRI_UNKNOWN_MEM_ZONE);
    filename->appendText(_directory);
    filename->appendText("/tmp-");
    filename->appendInteger(++counter);

    int fd = TRI_OPEN(filename->c_str(), O_RDWR | O_CREAT);

    if (fd) {
      ::write(fd, blob, strlen(blob));
      ::close(fd);
    }
    else {
      BOOST_CHECK_EQUAL(false, true);
    }

    return filename;
  }

  StringBuffer _directory;
};

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief setup
////////////////////////////////////////////////////////////////////////////////

BOOST_FIXTURE_TEST_SUITE(CFilesTest, CFilesSetup)

////////////////////////////////////////////////////////////////////////////////
/// @brief test file exists
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_existsfile) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(true, TRI_ExistsFile(filename->c_str()));
  TRI_UnlinkFile(filename->c_str());

  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size empty file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_empty) {
  StringBuffer* filename = writeFile("");
  BOOST_CHECK_EQUAL(0, (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_exists) {
  const char* buffer = "the quick brown fox";

  StringBuffer* filename = writeFile(buffer);
  BOOST_CHECK_EQUAL(strlen(buffer), (int) TRI_SizeFile(filename->c_str()));

  TRI_UnlinkFile(filename->c_str());
  delete filename;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief test file size, non existing file
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_CASE (tst_filesize_non) {
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("h5uuuuui3unn645wejhdjhikjdsf"));
  BOOST_CHECK_EQUAL((int) -1, (int) TRI_SizeFile("dihnui8ngiu54"));
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generate tests
////////////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE_END ()

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:
<|endoftext|>


<commit_before>// Licensed under a 3-clause BSD style license - see LICENSE.rst

// Fast range median distance computations for dataset `y`:
//
//    mu(l, r) = median(y[l:r+1])
//    dist(l, r) = sum(abs(x - mu(l, r)) for x in y[l:r+1])
//
// and an implementation of the find-best-partition dynamic program.
//
// We don't implement a rolling median computation, on the assumption that
// accesses are concentrated on small windows in the data.

#include <vector>
#include <queue>
#include <limits>
#include <map>
#include <algorithm>

#include <Python.h>

#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }

//
// Median computation.
//

template <class const_iterator>
void compute_median(const_iterator start, const_iterator end, double *mu, double *dist)
{
    size_t n = end - start;
    std::vector<double> tmp;
    std::vector<double>::iterator nth;
    tmp.insert(tmp.end(), start, end);

    if (start >= end) {
        *mu = 0;
    }
    else {
        nth = tmp.begin() + n/2;
        std::nth_element(tmp.begin(), nth, tmp.end());

        if (n % 2 == 0) {
            *mu = (*nth + *std::max_element(tmp.begin(), nth)) / 2;
        }
        else {
            *mu = *nth;
        }
    }

    *dist = 0;
    for (const_iterator it = start; it < end; ++it) {
        *dist += fabs(*it - *mu);
    }
}

//
// Cache for cache[left,right] == (mu, dist)
//

class Cache
{
private:
    struct Item
    {
        size_t left, right;
        double mu, dist;
    };

    std::vector<Item> items_;

    size_t idx(size_t left, size_t right) const {
        // Enumeration of pairs
        size_t n = right - left;
        n = (n + left) * (n + left + 1) / 2 + n;
        return n % items_.size();
    }

public:
    Cache(size_t size) : items_(size) {
        std::vector<Item>::iterator it;
        for (it = items_.begin(); it < items_.end(); ++it) {
            it->left = -1;
        }
    }

    bool get(size_t left, size_t right, double *mu, double *dist) const {
        size_t i = idx(left, right);
        if (items_[i].left == left && items_[i].right == right) {
            *mu = items_[i].mu;
            *dist = items_[i].dist;
            return true;
        }
        return false;
    }

    void set(size_t left, size_t right, double mu, double dist) {
        size_t i = idx(left, right);
        items_[i].left = left;
        items_[i].right = right;
        items_[i].mu = mu;
        items_[i].dist = dist;
    }
};

//
// RangeMedian object.
//

typedef struct {
    PyObject_HEAD
    std::vector<double> *y;
    Cache *cache;
} RangeMedianObject;

PyObject *RangeMedian_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    RangeMedianObject *self;
    self = (RangeMedianObject*)type->tp_alloc(type, 0);
    self->y = NULL;
    self->cache = NULL;
    return (PyObject*)self;
}

int RangeMedian_init(RangeMedianObject *self, PyObject *args, PyObject *kwds)
{
    static const char *kwlist[] = {"y", NULL};
    PyObject *y_obj;
    Py_ssize_t size, k;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char**)kwlist,
                                     &PyList_Type, &y_obj)) {
        return -1;
    }

    size = PyList_GET_SIZE(y_obj);

    try {
        self->y = new std::vector<double>(size);

        // Multiplier based on hardcoded constant sizes in step_detect.py, about
        // this many accesses expected --- but prefer primes due to a modulo
        // calculation in the cache.
        self->cache = new Cache(37*size + 401);
    }
    catch (std::bad_alloc) {
        PyErr_SetString(PyExc_MemoryError, "Allocating memory failed");
        return -1;
    }

    for (k = 0; k < size; ++k) {
        PyObject *x;

        x = PyNumber_Float(PyList_GET_ITEM(y_obj, k));
        if (x == NULL || !PyFloat_Check(x)) {
            Py_XDECREF(x);
            return -1;
        }
        (*self->y)[k] = PyFloat_AS_DOUBLE(x);
        Py_DECREF(x);
    }

    return 0;
}

static void RangeMedian_dealloc(RangeMedianObject *self)
{
    delete self->y;
    delete self->cache;
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static int RangeMedian_mu_dist(RangeMedianObject *self, Py_ssize_t left, Py_ssize_t right,
                               double *mu, double *dist)
{
    Py_ssize_t size = (Py_ssize_t)self->y->size();

    if (left < 0 || right < 0 || left >= size || right >= size) {
        PyErr_SetString(PyExc_ValueError, "argument out of range");
        return -1;
    }

    if (!self->cache->get(left, right, mu, dist)) {
        compute_median(self->y->begin() + left, self->y->begin() + right + 1, mu, dist);
        self->cache->set(left, right, *mu, *dist);
    }

    return 0;
}

static PyObject *RangeMedian_mu(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t left, right;
    double mu = 0, dist;

    if (!PyArg_ParseTuple(args, "nn", &left, &right)) {
        return NULL;
    }

    if (RangeMedian_mu_dist(self, left, right, &mu, &dist) == -1) {
        return NULL;
    }

    return PyFloat_FromDouble(mu);
}

static PyObject *RangeMedian_dist(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t left, right;
    double mu, dist = 0;

    if (!PyArg_ParseTuple(args, "nn", &left, &right)) {
        return NULL;
    }

    if (RangeMedian_mu_dist(self, left, right, &mu, &dist) == -1) {
        return NULL;
    }

    return PyFloat_FromDouble(dist);
}

static PyObject *RangeMedian_precompute(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t max_size, min_pos, max_pos;

    if (!PyArg_ParseTuple(args, "nnn", &max_size, &min_pos, &max_pos)) {
        return NULL;
    }

    // noop

    Py_RETURN_NONE;
}

static PyObject *RangeMedian_find_best_partition(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t min_size, max_size, min_pos, max_pos;
    double gamma;
    Py_ssize_t size;

    if (!PyArg_ParseTuple(args, "dnnnn", &gamma, &min_size, &max_size, &min_pos, &max_pos)) {
        return NULL;
    }

    size = self->y->size();

    if (!(0 < min_size && min_size <= max_size &&
          0 <= min_pos && min_pos <= max_pos && max_pos <= size)) {
        PyErr_SetString(PyExc_ValueError, "invalid input indices");
        return NULL;
    }

    double inf = std::numeric_limits<double>::infinity();

    std::vector<double> B(max_pos - min_pos + 1);
    std::vector<Py_ssize_t> p(max_pos - min_pos);

    B[0] = -gamma;

    for (Py_ssize_t right = min_pos; right < max_pos; ++right) {
        B[right + 1 - min_pos] = inf;

        Py_ssize_t aa = std::max(right + 1 - max_size, min_pos);
        Py_ssize_t bb = std::max(right + 1 - min_size + 1, min_pos);
        for (Py_ssize_t left = aa; left < bb; ++left) {
            double mu, dist;
            if (RangeMedian_mu_dist(self, left, right, &mu, &dist) == -1) {
                return NULL;
            }

            double b = B[left - min_pos] + gamma + dist;
            if (b <= B[right + 1 - min_pos]) {
                B[right + 1 - min_pos] = b;
                p[right - min_pos] = left - 1;
            }
        }
    }

    PyObject *p_list;

    p_list = PyList_New(p.size());
    if (p_list == NULL) {
        return NULL;
    }

    for (Py_ssize_t k = 0; k < (Py_ssize_t)p.size(); ++k) {
#if PY_MAJOR_VERSION >= 3
        PyObject *num = PyLong_FromSsize_t(p[k]);
#else
        PyObject *num = PyInt_FromSsize_t(p[k]);
#endif
        if (num == NULL) {
            Py_DECREF(p_list);
            return NULL;
        }
        PyList_SET_ITEM(p_list, k, num);
    }

    return p_list;
}

//
// RangeMedian type.
//

static PyMethodDef RangeMedian_methods[] = {
    {"mu", (PyCFunction)RangeMedian_mu, METH_VARARGS, NULL},
    {"dist", (PyCFunction)RangeMedian_dist, METH_VARARGS, NULL},
    {"precompute", (PyCFunction)RangeMedian_precompute, METH_VARARGS, NULL},
    {"find_best_partition", (PyCFunction)RangeMedian_find_best_partition, METH_VARARGS, NULL},
    {NULL, NULL}
};

static PyTypeObject RangeMedianType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "RangeMedian",
    sizeof(RangeMedianObject),
    0,
    (destructor)RangeMedian_dealloc, // tp_dealloc
    0,                          // tp_print
    0,                          // tp_getattr
    0,                          // tp_setattr
    0,                          // tp_compare / tp_reserved
    0,                          // tp_repr
    0,                          // tp_as_number
    0,                          // tp_as_sequence
    0,                          // tp_as_mapping
    0,                          // tp_hash
    0,                          // tp_call
    0,                          // tp_str
    0,                          // tp_getattro
    0,                          // tp_setattro
    0,                          // tp_as_buffer
    Py_TPFLAGS_DEFAULT,         // tp_flags
    NULL,                       // tp_doc
    0,                          // tp_traverse
    0,                          // tp_clear
    0,                          // tp_richcompare
    0,                          // tp_weaklistoffset
    0,                          // tp_iter
    0,                          // tp_iternext
    RangeMedian_methods,        // tp_methods
    0,                          // tp_members
    0,                          // tp_getset
    0,                          // tp_base
    0,                          // tp_dict
    0,                          // tp_descr_get
    0,                          // tp_descr_set
    0,                          // tp_dictoffset
    (initproc)RangeMedian_init, // tp_init
    0,                          // tp_alloc
    RangeMedian_new,            // tp_new
    0,                          // tp_free
    0,                          // tp_is_gc
    0,                          // tp_bases
    0,                          // tp_mro
    0,                          // tp_cache
    0,                          // tp_subclasses
    0,                          // tp_weaklist
    0,                          // tp_del
    0,                          // tp_version_tag
};

static PyTypeObject *RangeMedian_init_type(PyObject *m)
{
#if PY_MAJOR_VERSION < 3
    RangeMedianType.ob_type = &PyType_Type;
#endif

    if (PyType_Ready(&RangeMedianType) < 0) {
        return NULL;
    }

    if (PyModule_AddObject(m, "RangeMedian", (PyObject *)&RangeMedianType) == -1) {
        return NULL;
    }

    return &RangeMedianType;
}

//
// Module initialization.
//

EXTERN_C_BEGIN

#if PY_MAJOR_VERSION >= 3

static struct PyModuleDef moduledef = {
        PyModuleDef_HEAD_INIT,
        "_rangemedian",
        NULL,
        0,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL
};

PyObject *PyInit__rangemedian(void)
{
    PyObject *m;

    m = PyModule_Create(&moduledef);
    if (m == NULL) {
        return NULL;
    }

    if (RangeMedian_init_type(m) == NULL) {
        return NULL;
    }

    return m;
}

#else

PyMODINIT_FUNC init_rangemedian(void)
{
    PyObject *m;

    m = Py_InitModule("_rangemedian", NULL);
    if (m == NULL) {
        return;
    }

    RangeMedian_init_type(m);
}

#endif

EXTERN_C_END
<commit_msg>Fix build warning in _rangemedian.cpp<commit_after>// Licensed under a 3-clause BSD style license - see LICENSE.rst

// Fast range median distance computations for dataset `y`:
//
//    mu(l, r) = median(y[l:r+1])
//    dist(l, r) = sum(abs(x - mu(l, r)) for x in y[l:r+1])
//
// and an implementation of the find-best-partition dynamic program.
//
// We don't implement a rolling median computation, on the assumption that
// accesses are concentrated on small windows in the data.

#include <vector>
#include <queue>
#include <limits>
#include <map>
#include <algorithm>

#include <Python.h>

#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }

//
// Median computation.
//

template <class const_iterator>
void compute_median(const_iterator start, const_iterator end, double *mu, double *dist)
{
    size_t n = end - start;
    std::vector<double> tmp;
    std::vector<double>::iterator nth;
    tmp.insert(tmp.end(), start, end);

    if (start >= end) {
        *mu = 0;
    }
    else {
        nth = tmp.begin() + n/2;
        std::nth_element(tmp.begin(), nth, tmp.end());

        if (n % 2 == 0) {
            *mu = (*nth + *std::max_element(tmp.begin(), nth)) / 2;
        }
        else {
            *mu = *nth;
        }
    }

    *dist = 0;
    for (const_iterator it = start; it < end; ++it) {
        *dist += fabs(*it - *mu);
    }
}

//
// Cache for cache[left,right] == (mu, dist)
//

class Cache
{
private:
    struct Item
    {
        size_t left, right;
        double mu, dist;
    };

    std::vector<Item> items_;

    size_t idx(size_t left, size_t right) const {
        // Enumeration of pairs
        size_t n = right - left;
        n = (n + left) * (n + left + 1) / 2 + n;
        return n % items_.size();
    }

public:
    Cache(size_t size) : items_(size) {
        std::vector<Item>::iterator it;
        for (it = items_.begin(); it < items_.end(); ++it) {
            it->left = -1;
        }
    }

    bool get(size_t left, size_t right, double *mu, double *dist) const {
        size_t i = idx(left, right);
        if (items_[i].left == left && items_[i].right == right) {
            *mu = items_[i].mu;
            *dist = items_[i].dist;
            return true;
        }
        return false;
    }

    void set(size_t left, size_t right, double mu, double dist) {
        size_t i = idx(left, right);
        items_[i].left = left;
        items_[i].right = right;
        items_[i].mu = mu;
        items_[i].dist = dist;
    }
};

//
// RangeMedian object.
//

typedef struct {
    PyObject_HEAD
    std::vector<double> *y;
    Cache *cache;
} RangeMedianObject;

PyObject *RangeMedian_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    RangeMedianObject *self;
    self = (RangeMedianObject*)type->tp_alloc(type, 0);
    self->y = NULL;
    self->cache = NULL;
    return (PyObject*)self;
}

int RangeMedian_init(RangeMedianObject *self, PyObject *args, PyObject *kwds)
{
    static const char *kwlist[] = {"y", NULL};
    PyObject *y_obj;
    Py_ssize_t size, k;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char**)kwlist,
                                     &PyList_Type, &y_obj)) {
        return -1;
    }

    size = PyList_GET_SIZE(y_obj);

    try {
        self->y = new std::vector<double>(size);

        // Multiplier based on hardcoded constant sizes in step_detect.py, about
        // this many accesses expected --- but prefer primes due to a modulo
        // calculation in the cache.
        self->cache = new Cache(37*size + 401);
    }
    catch (const std::bad_alloc&) {
        PyErr_SetString(PyExc_MemoryError, "Allocating memory failed");
        return -1;
    }

    for (k = 0; k < size; ++k) {
        PyObject *x;

        x = PyNumber_Float(PyList_GET_ITEM(y_obj, k));
        if (x == NULL || !PyFloat_Check(x)) {
            Py_XDECREF(x);
            return -1;
        }
        (*self->y)[k] = PyFloat_AS_DOUBLE(x);
        Py_DECREF(x);
    }

    return 0;
}

static void RangeMedian_dealloc(RangeMedianObject *self)
{
    delete self->y;
    delete self->cache;
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static int RangeMedian_mu_dist(RangeMedianObject *self, Py_ssize_t left, Py_ssize_t right,
                               double *mu, double *dist)
{
    Py_ssize_t size = (Py_ssize_t)self->y->size();

    if (left < 0 || right < 0 || left >= size || right >= size) {
        PyErr_SetString(PyExc_ValueError, "argument out of range");
        return -1;
    }

    if (!self->cache->get(left, right, mu, dist)) {
        compute_median(self->y->begin() + left, self->y->begin() + right + 1, mu, dist);
        self->cache->set(left, right, *mu, *dist);
    }

    return 0;
}

static PyObject *RangeMedian_mu(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t left, right;
    double mu = 0, dist;

    if (!PyArg_ParseTuple(args, "nn", &left, &right)) {
        return NULL;
    }

    if (RangeMedian_mu_dist(self, left, right, &mu, &dist) == -1) {
        return NULL;
    }

    return PyFloat_FromDouble(mu);
}

static PyObject *RangeMedian_dist(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t left, right;
    double mu, dist = 0;

    if (!PyArg_ParseTuple(args, "nn", &left, &right)) {
        return NULL;
    }

    if (RangeMedian_mu_dist(self, left, right, &mu, &dist) == -1) {
        return NULL;
    }

    return PyFloat_FromDouble(dist);
}

static PyObject *RangeMedian_precompute(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t max_size, min_pos, max_pos;

    if (!PyArg_ParseTuple(args, "nnn", &max_size, &min_pos, &max_pos)) {
        return NULL;
    }

    // noop

    Py_RETURN_NONE;
}

static PyObject *RangeMedian_find_best_partition(RangeMedianObject *self, PyObject *args)
{
    Py_ssize_t min_size, max_size, min_pos, max_pos;
    double gamma;
    Py_ssize_t size;

    if (!PyArg_ParseTuple(args, "dnnnn", &gamma, &min_size, &max_size, &min_pos, &max_pos)) {
        return NULL;
    }

    size = self->y->size();

    if (!(0 < min_size && min_size <= max_size &&
          0 <= min_pos && min_pos <= max_pos && max_pos <= size)) {
        PyErr_SetString(PyExc_ValueError, "invalid input indices");
        return NULL;
    }

    double inf = std::numeric_limits<double>::infinity();

    std::vector<double> B(max_pos - min_pos + 1);
    std::vector<Py_ssize_t> p(max_pos - min_pos);

    B[0] = -gamma;

    for (Py_ssize_t right = min_pos; right < max_pos; ++right) {
        B[right + 1 - min_pos] = inf;

        Py_ssize_t aa = std::max(right + 1 - max_size, min_pos);
        Py_ssize_t bb = std::max(right + 1 - min_size + 1, min_pos);
        for (Py_ssize_t left = aa; left < bb; ++left) {
            double mu, dist;
            if (RangeMedian_mu_dist(self, left, right, &mu, &dist) == -1) {
                return NULL;
            }

            double b = B[left - min_pos] + gamma + dist;
            if (b <= B[right + 1 - min_pos]) {
                B[right + 1 - min_pos] = b;
                p[right - min_pos] = left - 1;
            }
        }
    }

    PyObject *p_list;

    p_list = PyList_New(p.size());
    if (p_list == NULL) {
        return NULL;
    }

    for (Py_ssize_t k = 0; k < (Py_ssize_t)p.size(); ++k) {
#if PY_MAJOR_VERSION >= 3
        PyObject *num = PyLong_FromSsize_t(p[k]);
#else
        PyObject *num = PyInt_FromSsize_t(p[k]);
#endif
        if (num == NULL) {
            Py_DECREF(p_list);
            return NULL;
        }
        PyList_SET_ITEM(p_list, k, num);
    }

    return p_list;
}

//
// RangeMedian type.
//

static PyMethodDef RangeMedian_methods[] = {
    {"mu", (PyCFunction)RangeMedian_mu, METH_VARARGS, NULL},
    {"dist", (PyCFunction)RangeMedian_dist, METH_VARARGS, NULL},
    {"precompute", (PyCFunction)RangeMedian_precompute, METH_VARARGS, NULL},
    {"find_best_partition", (PyCFunction)RangeMedian_find_best_partition, METH_VARARGS, NULL},
    {NULL, NULL}
};

static PyTypeObject RangeMedianType = {
#if PY_MAJOR_VERSION >= 3
    PyVarObject_HEAD_INIT(NULL, 0)
#else
    PyObject_HEAD_INIT(NULL)
    0,
#endif
    "RangeMedian",
    sizeof(RangeMedianObject),
    0,
    (destructor)RangeMedian_dealloc, // tp_dealloc
    0,                          // tp_print
    0,                          // tp_getattr
    0,                          // tp_setattr
    0,                          // tp_compare / tp_reserved
    0,                          // tp_repr
    0,                          // tp_as_number
    0,                          // tp_as_sequence
    0,                          // tp_as_mapping
    0,                          // tp_hash
    0,                          // tp_call
    0,                          // tp_str
    0,                          // tp_getattro
    0,                          // tp_setattro
    0,                          // tp_as_buffer
    Py_TPFLAGS_DEFAULT,         // tp_flags
    NULL,                       // tp_doc
    0,                          // tp_traverse
    0,                          // tp_clear
    0,                          // tp_richcompare
    0,                          // tp_weaklistoffset
    0,                          // tp_iter
    0,                          // tp_iternext
    RangeMedian_methods,        // tp_methods
    0,                          // tp_members
    0,                          // tp_getset
    0,                          // tp_base
    0,                          // tp_dict
    0,                          // tp_descr_get
    0,                          // tp_descr_set
    0,                          // tp_dictoffset
    (initproc)RangeMedian_init, // tp_init
    0,                          // tp_alloc
    RangeMedian_new,            // tp_new
    0,                          // tp_free
    0,                          // tp_is_gc
    0,                          // tp_bases
    0,                          // tp_mro
    0,                          // tp_cache
    0,                          // tp_subclasses
    0,                          // tp_weaklist
    0,                          // tp_del
    0,                          // tp_version_tag
};

static PyTypeObject *RangeMedian_init_type(PyObject *m)
{
#if PY_MAJOR_VERSION < 3
    RangeMedianType.ob_type = &PyType_Type;
#endif

    if (PyType_Ready(&RangeMedianType) < 0) {
        return NULL;
    }

    if (PyModule_AddObject(m, "RangeMedian", (PyObject *)&RangeMedianType) == -1) {
        return NULL;
    }

    return &RangeMedianType;
}

//
// Module initialization.
//

EXTERN_C_BEGIN

#if PY_MAJOR_VERSION >= 3

static struct PyModuleDef moduledef = {
        PyModuleDef_HEAD_INIT,
        "_rangemedian",
        NULL,
        0,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL
};

PyObject *PyInit__rangemedian(void)
{
    PyObject *m;

    m = PyModule_Create(&moduledef);
    if (m == NULL) {
        return NULL;
    }

    if (RangeMedian_init_type(m) == NULL) {
        return NULL;
    }

    return m;
}

#else

PyMODINIT_FUNC init_rangemedian(void)
{
    PyObject *m;

    m = Py_InitModule("_rangemedian", NULL);
    if (m == NULL) {
        return;
    }

    RangeMedian_init_type(m);
}

#endif

EXTERN_C_END
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkNrrdImageReadWriteTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include <fstream>
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImage.h"

int itkNrrdImageReadWriteTest( int ac, char* av[] )
{
  if(ac < 2)
    {
    std::cerr << "Usage: " << av[0] << " Input Output\n";
    return EXIT_FAILURE;
    }

  typedef float PixelType;
  typedef itk::Image<PixelType, 3> myImage;

  itk::ImageFileReader<myImage>::Pointer reader
                                  = itk::ImageFileReader<myImage>::New();
  reader->SetFileName(av[1]);

  try
    {
    reader->Update();
    }
  catch (itk::ExceptionObject & e)
    {
    std::cerr << "exception in file reader " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;
    }

  myImage::Pointer image = reader->GetOutput();
  image->Print(std::cout );

  // Generate test image
  itk::ImageFileWriter<myImage>::Pointer writer;
  writer = itk::ImageFileWriter<myImage>::New();
  writer->SetInput( reader->GetOutput() );
  writer->SetFileName(av[2]);
  writer->Update();

  return EXIT_SUCCESS;

}
<commit_msg>BUG: exceptions were never caught for errors during write<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkNrrdImageReadWriteTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include <fstream>
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImage.h"

int itkNrrdImageReadWriteTest( int ac, char* av[] )
{
  if(ac < 2)
    {
    std::cerr << "Usage: " << av[0] << " Input Output\n";
    return EXIT_FAILURE;
    }

  typedef float PixelType;
  typedef itk::Image<PixelType, 3> myImage;

  itk::ImageFileReader<myImage>::Pointer reader
                                  = itk::ImageFileReader<myImage>::New();
  reader->SetFileName(av[1]);

  try
    {
    reader->Update();
    }
  catch (itk::ExceptionObject & e)
    {
    std::cerr << "exception in file reader " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;
    }

  myImage::Pointer image = reader->GetOutput();
  image->Print(std::cout );

  // Generate test image
  itk::ImageFileWriter<myImage>::Pointer writer;
  writer = itk::ImageFileWriter<myImage>::New();
  writer->SetInput( reader->GetOutput() );
  writer->SetFileName(av[2]);
  try
    {
    writer->Update();
    }
  catch (itk::ExceptionObject & e)
    {
    std::cerr << "exception in file writer " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include "preprocessor/LandmarkIsomap.h"
#ifdef HAVE_LAPACK
#include "preprocessor/DimensionReductionPreprocessor.h"
#include "lib/lapack.h"
#include "preprocessor/LandmarkMDS.h"
#include "lib/common.h"
#include "lib/Mathematics.h"
#include "lib/io.h"
#include "distance/EuclidianDistance.h"
#include "distance/CustomDistance.h"
#include "lib/Signal.h"

using namespace shogun;

CLandmarkIsomap::CLandmarkIsomap() : CLandmarkMDS(), m_k(3)
{
}

CLandmarkIsomap::~CLandmarkIsomap()
{
}

bool CLandmarkIsomap::init(CFeatures* features)
{
	return true;
}

void CLandmarkIsomap::cleanup()
{
}

CCustomDistance* CLandmarkIsomap::approx_geodesic_distance(CDistance* distance)
{
	int32_t N,k,i,j;
	float64_t* D_matrix;
	distance->get_distance_matrix(&D_matrix,&N,&N);
	ASSERT(m_k<=N);

	float64_t* row = new float64_t[N];
	int32_t* row_idx = new int32_t[N];

	// cut-off by k
	for (i=0; i<N; i++)
	{
		for (j=0; j<N; j++)
		{
			row[j] = D_matrix[i*N+j];
			row_idx[j] = j;
		}

		CMath::qsort_index(row,row_idx,N);

		for (j=m_k+1; j<N; j++)
		{
			if (i!=row_idx[j])
				D_matrix[i*N+row_idx[j]] = CMath::ALMOST_INFTY;
		}
	}

	delete[] row;
	delete[] row_idx;

	// floyd-warshall
	for (k=0; k<N; k++)
	{
		for (i=0; i<N; i++)
		{
			for (j=0; j<N; j++)
				D_matrix[i*N+j] = CMath::min(D_matrix[i*N+j], D_matrix[i*N+k] + D_matrix[k*N+j]);
		}
	}

	CCustomDistance* geodesic_distance = new CCustomDistance(D_matrix,N,N);
	delete[] D_matrix;

	return geodesic_distance;
}

CSimpleFeatures<float64_t>* CLandmarkIsomap::apply_to_distance(CDistance* distance)
{
	ASSERT(distance);

	CCustomDistance* geodesic_distance = approx_geodesic_distance(distance);

	SGMatrix<float64_t> new_feature_matrix =
			CLandmarkMDS::embed_by_distance(geodesic_distance);

	delete geodesic_distance;

	CSimpleFeatures<float64_t>* new_features =
			new CSimpleFeatures<float64_t>(new_feature_matrix);

	return new_features;
}

SGMatrix<float64_t> CLandmarkIsomap::apply_to_feature_matrix(CFeatures* features)
{
	CSimpleFeatures<float64_t>* simple_features = (CSimpleFeatures<float64_t>*) features;

	CDistance* distance = new CEuclidianDistance(simple_features,simple_features);

	CCustomDistance* geodesic_distance = approx_geodesic_distance(distance);

	SGMatrix<float64_t> new_feature_matrix =
			CLandmarkMDS::embed_by_distance(geodesic_distance);

	delete geodesic_distance;

	simple_features->set_feature_matrix(new_feature_matrix);

	return new_feature_matrix;
}

SGVector<float64_t> CLandmarkIsomap::apply_to_feature_vector(SGVector<float64_t> vector)
{
	SG_NOTIMPLEMENTED;
	return vector;
}

#endif /* HAVE_LAPACK */
<commit_msg>Added check for connectiveness at LandmarkIsomap<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011 Sergey Lisitsyn
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include "preprocessor/LandmarkIsomap.h"
#ifdef HAVE_LAPACK
#include "preprocessor/DimensionReductionPreprocessor.h"
#include "lib/lapack.h"
#include "preprocessor/LandmarkMDS.h"
#include "lib/common.h"
#include "lib/Mathematics.h"
#include "lib/io.h"
#include "distance/EuclidianDistance.h"
#include "distance/CustomDistance.h"
#include "lib/Signal.h"

using namespace shogun;

CLandmarkIsomap::CLandmarkIsomap() : CLandmarkMDS(), m_k(3)
{
}

CLandmarkIsomap::~CLandmarkIsomap()
{
}

bool CLandmarkIsomap::init(CFeatures* features)
{
	return true;
}

void CLandmarkIsomap::cleanup()
{
}

CCustomDistance* CLandmarkIsomap::approx_geodesic_distance(CDistance* distance)
{
	int32_t N,k,i,j;
	float64_t* D_matrix;
	distance->get_distance_matrix(&D_matrix,&N,&N);
	ASSERT(m_k<=N);

	float64_t* row = new float64_t[N];
	int32_t* row_idx = new int32_t[N];

	// cut-off by k
	for (i=0; i<N; i++)
	{
		for (j=0; j<N; j++)
		{
			row[j] = D_matrix[i*N+j];
			row_idx[j] = j;
		}
		CMath::qsort_index(row,row_idx,N);
		for (j=m_k+1; j<N; j++)
		{
			D_matrix[i*N+row_idx[j]] = CMath::ALMOST_INFTY;
			D_matrix[row_idx[j]*N+i] = D_matrix[i*N+row_idx[j]];
		}
	}

	delete[] row;
	delete[] row_idx;

	// floyd-warshall
	for (k=0; k<N; k++)
	{
		for (i=0; i<N; i++)
		{
			for (j=0; j<N; j++)
				if (D_matrix[i*N+k]<CMath::ALMOST_INFTY && D_matrix[k*N+j]<CMath::ALMOST_INFTY)
					D_matrix[i*N+j] =
						CMath::min(D_matrix[i*N+j],
								   D_matrix[i*N+k] + D_matrix[k*N+j]);
		}
	}

	//check connectivity
	for (i=0; i<N*N; i++)
	{
		if (D_matrix[i] == CMath::ALMOST_INFTY)
			SG_ERROR("Graph is not connected");
	}

	CCustomDistance* geodesic_distance = new CCustomDistance(D_matrix,N,N);
	delete[] D_matrix;

	return geodesic_distance;
}

CSimpleFeatures<float64_t>* CLandmarkIsomap::apply_to_distance(CDistance* distance)
{
	ASSERT(distance);

	CCustomDistance* geodesic_distance = approx_geodesic_distance(distance);

	SGMatrix<float64_t> new_feature_matrix =
			CLandmarkMDS::embed_by_distance(geodesic_distance);

	delete geodesic_distance;

	CSimpleFeatures<float64_t>* new_features =
			new CSimpleFeatures<float64_t>(new_feature_matrix);

	return new_features;
}

SGMatrix<float64_t> CLandmarkIsomap::apply_to_feature_matrix(CFeatures* features)
{
	CSimpleFeatures<float64_t>* simple_features = (CSimpleFeatures<float64_t>*) features;

	CDistance* distance = new CEuclidianDistance(simple_features,simple_features);

	CCustomDistance* geodesic_distance = approx_geodesic_distance(distance);

	SGMatrix<float64_t> new_feature_matrix =
			CLandmarkMDS::embed_by_distance(geodesic_distance);

	delete geodesic_distance;

	simple_features->set_feature_matrix(new_feature_matrix);

	return new_feature_matrix;
}

SGVector<float64_t> CLandmarkIsomap::apply_to_feature_vector(SGVector<float64_t> vector)
{
	SG_NOTIMPLEMENTED;
	return vector;
}

#endif /* HAVE_LAPACK */
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

// Define the data types
typedef float inputDataType;
std::string inputTypeName("float");
std::string intermediateTypeName("float");
typedef float outputDataType;
std::string outputTypeName("float");

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size);

int main(int argc, char * argv[]) {
  bool reInit = false;
  uint8_t inputBits = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;
  PulsarSearch::DedispersionConf conf;
  cl::Event event;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    conf.setSplitSeconds(args.getSwitch("-split_seconds"));
    conf.setLocalMem(args.getSwitch("-local"));
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    inputBits = args.getSwitchArgument< unsigned int >("-input_bits");
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-split_seconds] [-local] -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

  // Allocate host memory
  std::vector< float > * shifts = PulsarSearch::getShifts(observation);
  observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));

	// Initialize OpenCL
	cl::Context clContext;
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();
  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);

	// Allocate device memory
  cl::Buffer shifts_d;
  cl::Buffer dispersedData_d;
  cl::Buffer dedispersedData_d;

  try {
  initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  } catch ( cl::Error & err ) {
    return -1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerSecond() % samples) == 0 || (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples local unroll samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread GFLOP/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
    conf.setNrSamplesPerBlock(*samples);

		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
      conf.setNrDMsPerBlock(*DMs);
			if ( conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock() > maxThreads ) {
				break;
			} else if ( (conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock()) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
        conf.setNrSamplesPerThread(samplesPerThread);
				if ( (observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 && (observation.getNrSamplesPerPaddedSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
          conf.setNrDMsPerThread(DMsPerThread);
					if ( (observation.getNrDMs() % (conf.getNrDMsPerBlock() * conf.getNrDMsPerThread())) != 0 ) {
						continue;
					} else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread()) + conf.getNrDMsPerThread() > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            conf.setUnroll(unroll);
            if ( (observation.getNrChannels() - 1) % conf.getUnroll() != 0 ) {
              continue;
            } else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread() * conf.getUnroll()) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            isa::utils::Timer timer;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(conf, inputBits, inputTypeName, intermediateTypeName, outputTypeName, observation, *shifts);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector < cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            unsigned int nrThreads = 0;
            if ( observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) == 0 ) {
              nrThreads = observation.getNrSamplesPerSecond() / conf.getNrSamplesPerThread();
            } else {
              nrThreads = observation.getNrSamplesPerPaddedSecond() / conf.getNrSamplesPerThread();
            }
            cl::NDRange global(nrThreads, observation.getNrDMs() / conf.getNrDMsPerThread());
            cl::NDRange local(conf.getNrSamplesPerBlock(), conf.getNrDMsPerBlock());

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution (";
              std::cerr << conf.print() << "): ";
              std::cerr << isa::utils::toString(err.err()) << "." << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size) {
  try {
    *shifts_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(float), 0, 0);
    *dispersedData_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, dispersedData_size * sizeof(dataType), 0, 0);
    *dedispersedData_d = cl::Buffer(clContext, CL_MEM_READ_WRITE, dedispersedData_size * sizeof(dataType), 0, 0);
    clQueue->enqueueWriteBuffer(*shifts_d, CL_FALSE, 0, shifts->size() * sizeof(float), reinterpret_cast< void * >(shifts->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<commit_msg>Forgot to update all dataType references in the previous commit.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

// Define the data types
typedef float inputDataType;
std::string inputTypeName("float");
std::string intermediateTypeName("float");
typedef float outputDataType;
std::string outputTypeName("float");

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size);

int main(int argc, char * argv[]) {
  bool reInit = false;
  uint8_t inputBits = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;
  PulsarSearch::DedispersionConf conf;
  cl::Event event;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    conf.setSplitSeconds(args.getSwitch("-split_seconds"));
    conf.setLocalMem(args.getSwitch("-local"));
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    inputBits = args.getSwitchArgument< unsigned int >("-input_bits");
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-split_seconds] [-local] -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

  // Allocate host memory
  std::vector< float > * shifts = PulsarSearch::getShifts(observation);
  observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));

	// Initialize OpenCL
	cl::Context clContext;
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();
  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);

	// Allocate device memory
  cl::Buffer shifts_d;
  cl::Buffer dispersedData_d;
  cl::Buffer dedispersedData_d;

  try {
  initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  } catch ( cl::Error & err ) {
    return -1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerSecond() % samples) == 0 || (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples local unroll samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread GFLOP/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
    conf.setNrSamplesPerBlock(*samples);

		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
      conf.setNrDMsPerBlock(*DMs);
			if ( conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock() > maxThreads ) {
				break;
			} else if ( (conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock()) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
        conf.setNrSamplesPerThread(samplesPerThread);
				if ( (observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 && (observation.getNrSamplesPerPaddedSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
          conf.setNrDMsPerThread(DMsPerThread);
					if ( (observation.getNrDMs() % (conf.getNrDMsPerBlock() * conf.getNrDMsPerThread())) != 0 ) {
						continue;
					} else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread()) + conf.getNrDMsPerThread() > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            conf.setUnroll(unroll);
            if ( (observation.getNrChannels() - 1) % conf.getUnroll() != 0 ) {
              continue;
            } else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread() * conf.getUnroll()) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            isa::utils::Timer timer;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(conf, inputBits, inputTypeName, intermediateTypeName, outputTypeName, observation, *shifts);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector < cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            unsigned int nrThreads = 0;
            if ( observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) == 0 ) {
              nrThreads = observation.getNrSamplesPerSecond() / conf.getNrSamplesPerThread();
            } else {
              nrThreads = observation.getNrSamplesPerPaddedSecond() / conf.getNrSamplesPerThread();
            }
            cl::NDRange global(nrThreads, observation.getNrDMs() / conf.getNrDMsPerThread());
            cl::NDRange local(conf.getNrSamplesPerBlock(), conf.getNrDMsPerBlock());

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution (";
              std::cerr << conf.print() << "): ";
              std::cerr << isa::utils::toString(err.err()) << "." << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size) {
  try {
    *shifts_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(float), 0, 0);
    *dispersedData_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, dispersedData_size * sizeof(inputDataType), 0, 0);
    *dedispersedData_d = cl::Buffer(clContext, CL_MEM_READ_WRITE, dedispersedData_size * sizeof(outputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*shifts_d, CL_FALSE, 0, shifts->size() * sizeof(float), reinterpret_cast< void * >(shifts->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE for licensing information
 */

#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/reversed.hpp>

#include "EnabledTransitions.hpp"

using boost::adaptors::indirect;
using boost::adaptors::reversed;

bool EnabledTransitions::allAncestorsMatched(const Transition & func) const {
    bool is_wait_or_test_type = func.getEnvelope().isWaitOrTestType();
    auto pid = func.pid;
    for (auto & curr : indirect(func.getAncestors())) {
        auto curr_env = curr.getEnvelope();
        auto curr_func = curr_env.func_id;
        if (!curr.isMatched()) {
            // Wei-Fan Chiang: I don't know why I need to add this line. But, I need it........
            if (curr_func == PCONTROL) {
                continue;
            }
            if (is_wait_or_test_type && /* !Scheduler::_send_block*/
                    curr_func == ISEND) {
                continue;
            }
            return false;
        } else if (curr_func == WAIT ||
                   curr_func == TEST ||
                   curr_func == WAITALL ||
                   curr_func == TESTALL) {

            for (auto & anc : indirect(curr.getAncestors())) {
                if (!anc.isMatched() && curr_env.matchSend(anc.getEnvelope())) {
                    return false;
                }
            }
        }
    }
    return true;
}

bool EnabledTransitions::anyAncestorMatched (const Trace & trace, const Transition & func) const {
    bool any_match = false;

    bool is_wait_or_test_type = func.getEnvelope().isWaitOrTestType();
    if (is_wait_or_test_type && func.getAncestors().empty()) {
        return true;
    }
    vector<shared_ptr<Transition> > filtered = func.getAncestors();
    for (auto req : trace.getRequestedProcs(func)) {
        if (req->isMatched() ||
                (is_wait_or_test_type && /*!Scheduler::_send_block &&*/
                    req->getEnvelope().func_id == ISEND)) {
            any_match = true;
        }
        filtered.erase(std::remove(filtered.begin(), filtered.end(), req), filtered.end());
    }
    if (!any_match) {
        return false;
    }
    for (auto & curr : indirect(filtered)) {
        if(!curr.isMatched()) {
            return false;
        }
    }

    return true;
}

/* Note that the use of reverse iterator here is for performance reason
 * so that we can break off the loop when we hit the last_matched
 * transition - If we stop using reverse iterator - we need to stop using
 * reverse iterator in GetMatchingSends as well - otherwise we won't
 * be able to preserve the program order matching of receives/sends */
vector<shared_ptr<Transition> > EnabledTransitions::create() const {
    vector<shared_ptr<Transition> > result;

    for (Trace & trace : state) {
        int last = trace.size() - 1;
        for (auto func_ptr : trace.reverse()) {
            auto & func = *func_ptr;
            auto pid = func.pid;
            if (!func.isMatched()) {
                const auto func_name = func.getEnvelope().func_id;
                if ((func_name != WAITANY && func_name != TESTANY) &&
                        allAncestorsMatched(func)) {
                    result.push_back(func_ptr);
                } else if ((func_name == WAITANY || func_name == TESTANY) &&
                        anyAncestorMatched(trace, func)) {
                    result.push_back(func_ptr);
                }
            }
            last--;
            if (auto last_matched = trace.findLastMatched()) {
                if (last <= (*last_matched)->index) {
                    break;
                }
            }
        }
    }
    return result;
}
<commit_msg>Removed unused code.<commit_after>/*
 * Copyright (c) 2008-2009
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE for licensing information
 */

#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/reversed.hpp>

#include "EnabledTransitions.hpp"

using boost::adaptors::indirect;
using boost::adaptors::reversed;

bool EnabledTransitions::allAncestorsMatched(const Transition & func) const {
    bool is_wait_or_test_type = func.getEnvelope().isWaitOrTestType();
    auto pid = func.pid;
    for (auto & curr : indirect(func.getAncestors())) {
        auto curr_env = curr.getEnvelope();
        auto curr_func = curr_env.func_id;
        if (!curr.isMatched()) {
            // Wei-Fan Chiang: I don't know why I need to add this line. But, I need it........
            if (curr_func == PCONTROL) {
                continue;
            }
            if (is_wait_or_test_type && /* !Scheduler::_send_block*/
                    curr_func == ISEND) {
                continue;
            }
            return false;
        } else if (curr_func == WAIT ||
                   curr_func == TEST ||
                   curr_func == WAITALL ||
                   curr_func == TESTALL) {
            for (auto & anc : indirect(curr.getAncestors())) {
                if (!anc.isMatched() && curr_env.matchSend(anc.getEnvelope())) {
                    return false;
                }
            }
        }
    }
    return true;
}

bool EnabledTransitions::anyAncestorMatched (const Trace & trace, const Transition & func) const {
    bool any_match = false;

    bool is_wait_or_test_type = func.getEnvelope().isWaitOrTestType();
    if (is_wait_or_test_type && func.getAncestors().empty()) {
        return true;
    }
    vector<shared_ptr<Transition> > filtered = func.getAncestors();
    for (auto req : trace.getRequestedProcs(func)) {
        if (req->isMatched() ||
                (is_wait_or_test_type && /*!Scheduler::_send_block &&*/
                    req->getEnvelope().func_id == ISEND)) {
            any_match = true;
        }
        filtered.erase(std::remove(filtered.begin(), filtered.end(), req), filtered.end());
    }
    if (!any_match) {
        return false;
    }
    for (auto & curr : indirect(filtered)) {
        if(!curr.isMatched()) {
            return false;
        }
    }

    return true;
}

/* Note that the use of reverse iterator here is for performance reason
 * so that we can break off the loop when we hit the last_matched
 * transition - If we stop using reverse iterator - we need to stop using
 * reverse iterator in GetMatchingSends as well - otherwise we won't
 * be able to preserve the program order matching of receives/sends */
vector<shared_ptr<Transition> > EnabledTransitions::create() const {
    vector<shared_ptr<Transition> > result;

    for (Trace & trace : state) {
        int last = trace.size() - 1;
        for (auto func_ptr : trace.reverse()) {
            auto & func = *func_ptr;
            if (!func.isMatched()) {
                const auto func_name = func.getEnvelope().func_id;
                if ((func_name != WAITANY && func_name != TESTANY) &&
                        allAncestorsMatched(func)) {
                    result.push_back(func_ptr);
                } else if ((func_name == WAITANY || func_name == TESTANY) &&
                        anyAncestorMatched(trace, func)) {
                    result.push_back(func_ptr);
                }
            }
            last--;
            if (auto last_matched = trace.findLastMatched()) {
                if (last <= (*last_matched)->index) {
                    break;
                }
            }
        }
    }
    return result;
}
<|endoftext|>


<commit_before>#pragma once

#include <GLFW/glfw3.h>
#include <json/json.h>
#include <vector>

class Input {
    public:
        /// The information needed to identify a button.
        struct Button {
            /// A string describing the action, e.g "Fire".
            char action[255];

            /// The GLFW key to press.
            int key;

            /// The GLFW state of that key.
            int state;
        };
        /// The buttons to register.
        std::vector<Button*> buttons;
        /// Gets the input singleton instance.
        /**
         * @return The input instance.
         */
        static Input& GetInstance() {
            static Input instance;
            return instance;
        }

        /// Sets the window to check for input against.
        /**
         * @param window The target GLFWwindow.
         */
        void SetWindow(GLFWwindow* window);

        /// Check if a button was activated this frame.
        /**
         * @param index The index of the button in the buttons array.
         */
        bool CheckButton(int index) const;

        ///Saves the buttons to a Json value.
        /**
         * @return The saved json value.
         */
        Json::Value Save() const;

        ///Saves the buttons to a Json value.
        /**
         * @param buttonsNode the json value to load.
         */
        void Load(const Json::Value& buttonsNode);

    private:
        GLFWwindow* window;

        Input() {}

        Input(Input const&);
        void operator=(Input const&);
};
<commit_msg>Document Input<commit_after>#pragma once

#include <GLFW/glfw3.h>
#include <json/json.h>
#include <vector>

/// Hold information about the hymn's inputs.
class Input {
    public:
        /// The information needed to identify a button.
        struct Button {
            /// A string describing the action, e.g "Fire".
            char action[255];

            /// The GLFW key to press.
            int key;

            /// The GLFW state of that key.
            int state;
        };

        /// The buttons to register.
        std::vector<Button*> buttons;

        /// Get the input singleton instance.
        /**
         * @return The input instance.
         */
        static Input& GetInstance() {
            static Input instance;
            return instance;
        }

        /// Set the window to check for input against.
        /**
         * @param window The target GLFWwindow.
         */
        void SetWindow(GLFWwindow* window);

        /// Check if a button was activated this frame.
        /**
         * @param index The index of the button in the buttons array.
         * @return Whether the button was activated this frame.
         */
        bool CheckButton(int index) const;

        /// Save the buttons to a JSON value.
        /**
         * @return The saved JSON value.
         */
        Json::Value Save() const;

        /// Load buttons from JSON node.
        /**
         * @param buttonsNode The JSON value to load.
         */
        void Load(const Json::Value& buttonsNode);

    private:
        GLFWwindow* window;

        Input() {}

        Input(Input const&);
        void operator=(Input const&);
};
<|endoftext|>