<commit_before>#ifndef EBITEN_GRAPHICS_AFFINE_MATRIX_HPP
#define EBITEN_GRAPHICS_AFFINE_MATRIX_HPP

#include <array>
#include <cassert>
#include <mutex>

namespace ebiten {
namespace graphics {

template<class Float, std::size_t Dimension, class Self>
class affine_matrix {
  static_assert(0 < Dimension, "Dimension must be more than 0");
private:
  static std::size_t const size_ = Dimension * (Dimension - 1);
  typedef std::array<Float, size_> elements_type;
  static std::once_flag identity_once_flag_;
protected:
  elements_type elements_;
protected:
  affine_matrix() {
    this->elements_.fill(0);
  }
public:
  template<std::size_t I, std::size_t J>
  Float
  element() const {
    static_assert(I < Dimension, "I must be less than Dimension");
    static_assert(J < Dimension, "J must be less than Dimension");
    if (I == Dimension - 1) {
      if (J == Dimension - 1) {
        return 1;
      }
      return 0;
    }
    return this->elements_[I * Dimension + J];
  }
  template<std::size_t I, std::size_t J>
  Float
  set_element(Float element) {
    static_assert(I < Dimension - 1, "I must be less than Dimension - 1");
    static_assert(J < Dimension,     "J must be less than Dimension");
    return this->elements_[I * Dimension + J] = element;
  }
  bool
  is_identity() const {
    typename elements_type::const_iterator it = this->elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          if (*it != 1) {
            return false;
          }
        } else {
          if (*it != 0) {
            return false;
          }
        }
      }
    }
    return true;
  }
  static Self
  identity() {
    static Self identity_;
    std::call_once(identity_once_flag_, initialize_identity, std::ref<Self>(identity_));
    return identity_;
  }
private:
  static void
  initialize_identity(Self& identity) {
    typename elements_type::iterator it = identity.elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          *it = 1;
        } else {
          *it = 0;
        }
      }
    }
  }
};

template<class Float, std::size_t Dimension, class Self>
std::once_flag affine_matrix<Float, Dimension, Self>::identity_once_flag_;

}
}

// TODO: test...

#ifdef EBITEN_TEST

namespace ebiten {
namespace graphics {

/*TEST(affine_matrix, element) {
  affine_matrix<double, 4> m;
  m.set_element<0, 0>(1);
  m.set_element<0, 1>(2);
  m.set_element<0, 2>(3);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(0, (m.element<1, 0>()));
  EXPECT_EQ(0, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(0, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
  m.set_element<1, 0>(4);
  m.set_element<1, 1>(5);
  m.set_element<2, 3>(6);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(4, (m.element<1, 0>()));
  EXPECT_EQ(5, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(6, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
}

TEST(affine_matrix, is_identity) {
  affine_matrix<double, 4> m1;
  m1.set_element<0, 0>(1);
  m1.set_element<1, 1>(1);
  m1.set_element<2, 2>(1);
  EXEPT_TRUE(m1.is_identity());
  affine_matrix<double, 4> m2 = m1;
  EXEPT_TRUE(m2.is_identity());
  m2.set_element<0, 1>(1);
  EXEPT_FALSE(m2.is_identity());
  }*/

}
}

#endif

#endif
<commit_msg>Added tests for affine_matrix<commit_after>#ifndef EBITEN_GRAPHICS_AFFINE_MATRIX_HPP
#define EBITEN_GRAPHICS_AFFINE_MATRIX_HPP

#include <array>
#include <cassert>
#include <mutex>

namespace ebiten {
namespace graphics {

template<class Float, std::size_t Dimension, class Self>
class affine_matrix {
  static_assert(0 < Dimension, "Dimension must be more than 0");
#ifdef EBITEN_TEST
private:
  FRIEND_TEST(affine_matrix, element);
  FRIEND_TEST(affine_matrix, is_identity);
#endif
private:
  static std::size_t const size_ = Dimension * (Dimension - 1);
  typedef std::array<Float, size_> elements_type;
  static std::once_flag identity_once_flag_;
protected:
  elements_type elements_;
protected:
  affine_matrix() {
    this->elements_.fill(0);
  }
public:
  template<std::size_t I, std::size_t J>
  Float
  element() const {
    static_assert(I < Dimension, "I must be less than Dimension");
    static_assert(J < Dimension, "J must be less than Dimension");
    if (I == Dimension - 1) {
      if (J == Dimension - 1) {
        return 1;
      }
      return 0;
    }
    return this->elements_[I * Dimension + J];
  }
  template<std::size_t I, std::size_t J>
  Float
  set_element(Float element) {
    static_assert(I < Dimension - 1, "I must be less than Dimension - 1");
    static_assert(J < Dimension,     "J must be less than Dimension");
    return this->elements_[I * Dimension + J] = element;
  }
  bool
  is_identity() const {
    typename elements_type::const_iterator it = this->elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          if (*it != 1) {
            return false;
          }
        } else {
          if (*it != 0) {
            return false;
          }
        }
      }
    }
    return true;
  }
  static Self
  identity() {
    static Self identity_;
    std::call_once(identity_once_flag_, initialize_identity, std::ref<Self>(identity_));
    return identity_;
  }
private:
  static void
  initialize_identity(Self& identity) {
    typename elements_type::iterator it = identity.elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          *it = 1;
        } else {
          *it = 0;
        }
      }
    }
  }
};

template<class Float, std::size_t Dimension, class Self>
std::once_flag affine_matrix<Float, Dimension, Self>::identity_once_flag_;

}
}

#ifdef EBITEN_TEST

namespace ebiten {
namespace graphics {

template<class Float, std::size_t Dimension>
class affine_matrix_impl : public affine_matrix<Float,
                                                Dimension,
                                                affine_matrix_impl<Float, Dimension>> {
};

TEST(affine_matrix, element) {
  affine_matrix_impl<double, 4> m;
  m.set_element<0, 0>(1);
  m.set_element<0, 1>(2);
  m.set_element<0, 2>(3);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(0, (m.element<1, 0>()));
  EXPECT_EQ(0, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(0, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
  m.set_element<1, 0>(4);
  m.set_element<1, 1>(5);
  m.set_element<2, 3>(6);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(4, (m.element<1, 0>()));
  EXPECT_EQ(5, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(6, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
}

TEST(affine_matrix, is_identity) {
  affine_matrix_impl<double, 4> m1;
  m1.set_element<0, 0>(1);
  m1.set_element<1, 1>(1);
  m1.set_element<2, 2>(1);
  EXPECT_TRUE(m1.is_identity());
  affine_matrix_impl<double, 4> m2 = m1;
  EXPECT_TRUE(m2.is_identity());
  m2.set_element<0, 1>(1);
  EXPECT_FALSE(m2.is_identity());
}

}
}

#endif

#endif
<|endoftext|>


<commit_before>#ifndef DEFS_H
#define DEFS_H

namespace godot {

enum class Error {
	OK,
	FAILED, ///< Generic fail error
	ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
	ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
	ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
	ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
	ERR_OUT_OF_MEMORY, ///< Out of memory
	ERR_FILE_NOT_FOUND,
	ERR_FILE_BAD_DRIVE,
	ERR_FILE_BAD_PATH,
	ERR_FILE_NO_PERMISSION, // (10)
	ERR_FILE_ALREADY_IN_USE,
	ERR_FILE_CANT_OPEN,
	ERR_FILE_CANT_WRITE,
	ERR_FILE_CANT_READ,
	ERR_FILE_UNRECOGNIZED, // (15)
	ERR_FILE_CORRUPT,
	ERR_FILE_MISSING_DEPENDENCIES,
	ERR_FILE_EOF,
	ERR_CANT_OPEN, ///< Can't open a resource/socket/file
	ERR_CANT_CREATE, // (20)
	ERR_QUERY_FAILED,
	ERR_ALREADY_IN_USE,
	ERR_LOCKED, ///< resource is locked
	ERR_TIMEOUT,
	ERR_CANT_CONNECT, // (25)
	ERR_CANT_RESOLVE,
	ERR_CONNECTION_ERROR,
	ERR_CANT_AQUIRE_RESOURCE,
	ERR_CANT_FORK,
	ERR_INVALID_DATA, ///< Data passed is invalid	(30)
	ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
	ERR_ALREADY_EXISTS, ///< When adding, item already exists
	ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
	ERR_DATABASE_CANT_READ, ///< database is full
	ERR_DATABASE_CANT_WRITE, ///< database is full	(35)
	ERR_COMPILATION_FAILED,
	ERR_METHOD_NOT_FOUND,
	ERR_LINK_FAILED,
	ERR_SCRIPT_FAILED,
	ERR_CYCLIC_LINK, // (40)
	ERR_INVALID_DECLARATION,
	ERR_DUPLICATE_SYMBOL,
	ERR_PARSE_ERROR,
	ERR_BUSY,
	ERR_SKIP, // (45)
	ERR_HELP, ///< user requested help!!
	ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
	ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
	ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
	ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
};

} // namespace godot

#include <GodotGlobal.hpp>

typedef float real_t;

#define CMP_EPSILON 0.00001
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
#define Math_PI 3.14159265358979323846

#define _PLANE_EQ_DOT_EPSILON 0.999
#define _PLANE_EQ_D_EPSILON 0.0001

#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) x
#define unlikely(x) x
#endif

// Don't use this directly; instead, use any of the CRASH_* macros
#ifdef _MSC_VER
#define GENERATE_TRAP                       \
	__debugbreak();                         \
	/* Avoid warning about control paths */ \
	for (;;) {                              \
	}
#else
#define GENERATE_TRAP __builtin_trap();
#endif

// ERR/WARN macros
#ifndef WARN_PRINT
#define WARN_PRINT(msg) godot::Godot::print_warning(msg, __func__, __FILE__, __LINE__)
#endif

#ifndef WARN_PRINTS
#define WARN_PRINTS(msg) WARN_PRINT((msg).utf8().get_data())
#endif

#ifndef ERR_PRINT
#define ERR_PRINT(msg) godot::Godot::print_error(msg, __func__, __FILE__, __LINE__)
#endif

#ifndef ERR_PRINTS
#define ERR_PRINTS(msg) ERR_PRINT((msg).utf8().get_data())
#endif

#ifndef FATAL_PRINT
#define FATAL_PRINT(msg) ERR_PRINT(godot::String("FATAL: ") + (msg))
#endif

#ifndef ERR_MSG_INDEX
#define ERR_MSG_INDEX(index, size) (godot::String("Index ") + #index + "=" + godot::String::num_int64(index) + " out of size (" + #size + "=" + godot::String::num_int64(size) + ")")
#endif

#ifndef ERR_MSG_NULL
#define ERR_MSG_NULL(param) (godot::String("Parameter '") + #param + "' is null.")
#endif

#ifndef ERR_MSG_COND
#define ERR_MSG_COND(cond) (godot::String("Condition '") + #cond + "' is true.")
#endif

#ifndef ERR_FAIL_INDEX
#define ERR_FAIL_INDEX(index, size)                       \
	do {                                                  \
		if (unlikely((index) < 0 || (index) >= (size))) { \
			ERR_PRINT(ERR_MSG_INDEX(index, size));        \
			return;                                       \
		}                                                 \
	} while (0)
#endif

#ifndef ERR_FAIL_INDEX_V
#define ERR_FAIL_INDEX_V(index, size, ret)                \
	do {                                                  \
		if (unlikely((index) < 0 || (index) >= (size))) { \
			ERR_PRINT(ERR_MSG_INDEX(index, size));        \
			return ret;                                   \
		}                                                 \
	} while (0)
#endif

#ifndef ERR_FAIL_UNSIGNED_INDEX_V
#define ERR_FAIL_UNSIGNED_INDEX_V(index, size, ret) \
	do {                                            \
		if (unlikely((index) >= (size))) {          \
			ERR_PRINT(ERR_MSG_INDEX(index, size));  \
			return ret;                             \
		}                                           \
	} while (0)
#endif

#ifndef CRASH_BAD_INDEX
#define CRASH_BAD_INDEX(index, size)                      \
	do {                                                  \
		if (unlikely((index) < 0 || (index) >= (size))) { \
			FATAL_PRINT(ERR_MSG_INDEX(index, size));      \
			GENERATE_TRAP;                                \
		}                                                 \
	} while (0)
#endif

#ifndef ERR_FAIL_NULL
#define ERR_FAIL_NULL(param)                \
	do {                                    \
		if (unlikely(!param)) {             \
			ERR_PRINT(ERR_MSG_NULL(param)); \
			return;                         \
		}                                   \
	} while (0)
#endif

#ifndef ERR_FAIL_NULL_V
#define ERR_FAIL_NULL_V(param, ret)         \
	do {                                    \
		if (unlikely(!param)) {             \
			ERR_PRINT(ERR_MSG_NULL(param)); \
			return ret;                     \
		}                                   \
	} while (0)
#endif

#ifndef ERR_FAIL_COND
#define ERR_FAIL_COND(cond)                \
	do {                                   \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			return;                        \
		}                                  \
	} while (0)
#endif

#ifndef CRASH_COND
#define CRASH_COND(cond)                     \
	do {                                     \
		if (unlikely(cond)) {                \
			FATAL_PRINT(ERR_MSG_COND(cond)); \
			return;                          \
		}                                    \
	} while (0)
#endif

#ifndef ERR_FAIL_COND_V
#define ERR_FAIL_COND_V(cond, ret)         \
	do {                                   \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			return ret;                    \
		}                                  \
	} while (0)
#endif

#ifndef ERR_CONTINUE
#define ERR_CONTINUE(cond)                 \
	{                                      \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			continue;                      \
		}                                  \
	}
#endif

#ifndef ERR_BREAK
#define ERR_BREAK(cond)                    \
	{                                      \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			break;                         \
		}                                  \
	}
#endif

#ifndef ERR_FAIL
#define ERR_FAIL()                            \
	do {                                      \
		ERR_PRINT("Method/Function Failed."); \
		return;                               \
	} while (0)
#endif

#ifndef ERR_FAIL_V
#define ERR_FAIL_V(ret)                       \
	do {                                      \
		ERR_PRINT("Method/Function Failed."); \
		return ret;                           \
	} while (0)
#endif

#ifndef CRASH_NOW
#define CRASH_NOW()                             \
	do {                                        \
		FATAL_PRINT("Method/Function Failed."); \
		GENERATE_TRAP;                          \
	} while (0)
#endif

#endif // DEFS_H
<commit_msg>Fix alloca() not being included on some platforms<commit_after>#ifndef DEFS_H
#define DEFS_H

namespace godot {

enum class Error {
	OK,
	FAILED, ///< Generic fail error
	ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable
	ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet
	ERR_UNAUTHORIZED, ///< Missing credentials for requested resource
	ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5)
	ERR_OUT_OF_MEMORY, ///< Out of memory
	ERR_FILE_NOT_FOUND,
	ERR_FILE_BAD_DRIVE,
	ERR_FILE_BAD_PATH,
	ERR_FILE_NO_PERMISSION, // (10)
	ERR_FILE_ALREADY_IN_USE,
	ERR_FILE_CANT_OPEN,
	ERR_FILE_CANT_WRITE,
	ERR_FILE_CANT_READ,
	ERR_FILE_UNRECOGNIZED, // (15)
	ERR_FILE_CORRUPT,
	ERR_FILE_MISSING_DEPENDENCIES,
	ERR_FILE_EOF,
	ERR_CANT_OPEN, ///< Can't open a resource/socket/file
	ERR_CANT_CREATE, // (20)
	ERR_QUERY_FAILED,
	ERR_ALREADY_IN_USE,
	ERR_LOCKED, ///< resource is locked
	ERR_TIMEOUT,
	ERR_CANT_CONNECT, // (25)
	ERR_CANT_RESOLVE,
	ERR_CONNECTION_ERROR,
	ERR_CANT_AQUIRE_RESOURCE,
	ERR_CANT_FORK,
	ERR_INVALID_DATA, ///< Data passed is invalid	(30)
	ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
	ERR_ALREADY_EXISTS, ///< When adding, item already exists
	ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist
	ERR_DATABASE_CANT_READ, ///< database is full
	ERR_DATABASE_CANT_WRITE, ///< database is full	(35)
	ERR_COMPILATION_FAILED,
	ERR_METHOD_NOT_FOUND,
	ERR_LINK_FAILED,
	ERR_SCRIPT_FAILED,
	ERR_CYCLIC_LINK, // (40)
	ERR_INVALID_DECLARATION,
	ERR_DUPLICATE_SYMBOL,
	ERR_PARSE_ERROR,
	ERR_BUSY,
	ERR_SKIP, // (45)
	ERR_HELP, ///< user requested help!!
	ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior.
	ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames
	ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though
	ERR_WTF = ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above
};

} // namespace godot

#include <GodotGlobal.hpp>

// alloca() is non-standard. When using MSVC, it's in malloc.h.
#if defined(__linux__) || defined(__APPLE__) || defined(__MINGW32__)
#include <alloca.h>
#endif

typedef float real_t;

#define CMP_EPSILON 0.00001
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
#define Math_PI 3.14159265358979323846

#define _PLANE_EQ_DOT_EPSILON 0.999
#define _PLANE_EQ_D_EPSILON 0.0001

#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) x
#define unlikely(x) x
#endif

// Don't use this directly; instead, use any of the CRASH_* macros
#ifdef _MSC_VER
#define GENERATE_TRAP                       \
	__debugbreak();                         \
	/* Avoid warning about control paths */ \
	for (;;) {                              \
	}
#else
#define GENERATE_TRAP __builtin_trap();
#endif

// ERR/WARN macros
#ifndef WARN_PRINT
#define WARN_PRINT(msg) godot::Godot::print_warning(msg, __func__, __FILE__, __LINE__)
#endif

#ifndef WARN_PRINTS
#define WARN_PRINTS(msg) WARN_PRINT((msg).utf8().get_data())
#endif

#ifndef ERR_PRINT
#define ERR_PRINT(msg) godot::Godot::print_error(msg, __func__, __FILE__, __LINE__)
#endif

#ifndef ERR_PRINTS
#define ERR_PRINTS(msg) ERR_PRINT((msg).utf8().get_data())
#endif

#ifndef FATAL_PRINT
#define FATAL_PRINT(msg) ERR_PRINT(godot::String("FATAL: ") + (msg))
#endif

#ifndef ERR_MSG_INDEX
#define ERR_MSG_INDEX(index, size) (godot::String("Index ") + #index + "=" + godot::String::num_int64(index) + " out of size (" + #size + "=" + godot::String::num_int64(size) + ")")
#endif

#ifndef ERR_MSG_NULL
#define ERR_MSG_NULL(param) (godot::String("Parameter '") + #param + "' is null.")
#endif

#ifndef ERR_MSG_COND
#define ERR_MSG_COND(cond) (godot::String("Condition '") + #cond + "' is true.")
#endif

#ifndef ERR_FAIL_INDEX
#define ERR_FAIL_INDEX(index, size)                       \
	do {                                                  \
		if (unlikely((index) < 0 || (index) >= (size))) { \
			ERR_PRINT(ERR_MSG_INDEX(index, size));        \
			return;                                       \
		}                                                 \
	} while (0)
#endif

#ifndef ERR_FAIL_INDEX_V
#define ERR_FAIL_INDEX_V(index, size, ret)                \
	do {                                                  \
		if (unlikely((index) < 0 || (index) >= (size))) { \
			ERR_PRINT(ERR_MSG_INDEX(index, size));        \
			return ret;                                   \
		}                                                 \
	} while (0)
#endif

#ifndef ERR_FAIL_UNSIGNED_INDEX_V
#define ERR_FAIL_UNSIGNED_INDEX_V(index, size, ret) \
	do {                                            \
		if (unlikely((index) >= (size))) {          \
			ERR_PRINT(ERR_MSG_INDEX(index, size));  \
			return ret;                             \
		}                                           \
	} while (0)
#endif

#ifndef CRASH_BAD_INDEX
#define CRASH_BAD_INDEX(index, size)                      \
	do {                                                  \
		if (unlikely((index) < 0 || (index) >= (size))) { \
			FATAL_PRINT(ERR_MSG_INDEX(index, size));      \
			GENERATE_TRAP;                                \
		}                                                 \
	} while (0)
#endif

#ifndef ERR_FAIL_NULL
#define ERR_FAIL_NULL(param)                \
	do {                                    \
		if (unlikely(!param)) {             \
			ERR_PRINT(ERR_MSG_NULL(param)); \
			return;                         \
		}                                   \
	} while (0)
#endif

#ifndef ERR_FAIL_NULL_V
#define ERR_FAIL_NULL_V(param, ret)         \
	do {                                    \
		if (unlikely(!param)) {             \
			ERR_PRINT(ERR_MSG_NULL(param)); \
			return ret;                     \
		}                                   \
	} while (0)
#endif

#ifndef ERR_FAIL_COND
#define ERR_FAIL_COND(cond)                \
	do {                                   \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			return;                        \
		}                                  \
	} while (0)
#endif

#ifndef CRASH_COND
#define CRASH_COND(cond)                     \
	do {                                     \
		if (unlikely(cond)) {                \
			FATAL_PRINT(ERR_MSG_COND(cond)); \
			return;                          \
		}                                    \
	} while (0)
#endif

#ifndef ERR_FAIL_COND_V
#define ERR_FAIL_COND_V(cond, ret)         \
	do {                                   \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			return ret;                    \
		}                                  \
	} while (0)
#endif

#ifndef ERR_CONTINUE
#define ERR_CONTINUE(cond)                 \
	{                                      \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			continue;                      \
		}                                  \
	}
#endif

#ifndef ERR_BREAK
#define ERR_BREAK(cond)                    \
	{                                      \
		if (unlikely(cond)) {              \
			ERR_PRINT(ERR_MSG_COND(cond)); \
			break;                         \
		}                                  \
	}
#endif

#ifndef ERR_FAIL
#define ERR_FAIL()                            \
	do {                                      \
		ERR_PRINT("Method/Function Failed."); \
		return;                               \
	} while (0)
#endif

#ifndef ERR_FAIL_V
#define ERR_FAIL_V(ret)                       \
	do {                                      \
		ERR_PRINT("Method/Function Failed."); \
		return ret;                           \
	} while (0)
#endif

#ifndef CRASH_NOW
#define CRASH_NOW()                             \
	do {                                        \
		FATAL_PRINT("Method/Function Failed."); \
		GENERATE_TRAP;                          \
	} while (0)
#endif

#endif // DEFS_H
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*               Copyright 2007-2014 by Benjamin Seppke                 */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_PROJECTIVE_REGISTRATION_HXX
#define VIGRA_PROJECTIVE_REGISTRATION_HXX

#include "mathutil.hxx"
#include "matrix.hxx"
#include "linear_solve.hxx"
#include "tinyvector.hxx"
#include "splineimageview.hxx"

namespace vigra
{

/** \addtogroup Registration Image Registration
 */
//@{

/********************************************************/
/*                                                      */
/*     projectiveMatrix2DFromCorrespondingPoints        */
/*                                                      */
/********************************************************/

/** \brief Create homogeneous matrix that maps corresponding points onto each other.

    For use with \ref projectiveWarpImage(). Since four corresponding points are needed to be given,
    the matrix will compute a full projective transform.
 */
template <class SrcPointIterator, class DestPointIterator>
linalg::TemporaryMatrix<double>
projectiveMatrix2DFromCorrespondingPoints(SrcPointIterator s, SrcPointIterator send, DestPointIterator d)
{
    //Calculate the matrix using least squares of all points of points like the result is:
    // ( x2 )   ( s_x        r1        t_x )   ( x1 )
    // ( y2 ) = (  r2        s_y        t_y ) * ( y1 )
    // (  1 )   (  p1        p2        1   )   (  1 )
    int size = send - s;

    vigra_assert(size >= 4,
                 "projectiveMatrix2DFromCorrespondingPoints(): need at least four corresponding points.");

    vigra::Matrix<double> A(2*size,8, 0.0), b(2*size,1),  res(8,1);
    for (int i =0; i<size; ++i, ++s, ++d)
    {
        //m_00                m_01                m_02                m_10                    m_11                    m_12                m_20                                m_21
        //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        A(i,0)=(*d)[0];        A(i,1)=(*d)[1];        A(i,2)=1;            A(i,3)=0;                A(i,4)=0;                A(i,5)=0;            A(i,6)=-1*((*d)[0])*((*s)[0]);            A(i,7)=-1*((*d)[1])*((*s)[0]);
        b(i,0)=(*s)[0];

        A(size+i,0)=0;        A(size+i,1)=0;        A(size+i,2)=0;        A(size+i,3)=(*d)[0];    A(size+i,4)=(*d)[1];    A(size+i,5)=1;        A(size+i,6)=-1*((*d)[0])*((*s)[1]);        A(size+i,7)=-1*((*d)[1])*((*s)[1]);
        b(size+i,0)=(*s)[1];

    }

    vigra_assert(linearSolve(A, b, res),
                "projectiveMatrix2DFromCorrespondingPoints(): singular solution matrix.");

    linalg::TemporaryMatrix<double> projectiveMat(3,3);
    projectiveMat(0,0) = res(0,0);        projectiveMat(0,1) = res(1,0);        projectiveMat(0,2) = res(2,0);
    projectiveMat(1,0) = res(3,0);        projectiveMat(1,1) = res(4,0);        projectiveMat(1,2) = res(5,0);
    projectiveMat(2,0) = res(6,0);        projectiveMat(2,1) = res(7,0);        projectiveMat(2,2) = 1;

    return projectiveMat;
}

/********************************************************/
/*                                                      */
/*                projectiveWarpImage                   */
/*                                                      */
/********************************************************/

/** \brief Warp an image according to an projective transformation.

    The matrix can be computed from a set of correspondung points
    using \ref projectiveMatrix2DFromCorrespondingPoints().

     Declarations:

    \#include \<vigra/projective_registration.hxx\>

    Namespace: vigra

    pass 2D array views:
    \code
    namespace vigra {
        template <int ORDER, class T,
                  class T2, class S2,
                  class C>
        void
        projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                            MultiArrayView<2, T2, S2> dest,
                            MultiArrayView<2, double, C> const & projectiveMatrix);
    }
    \endcode

    \deprecatedAPI{projectiveWarpImage}
    pass \ref ImageIterators and \ref DataAccessors :

    pass arguments explicitly:
    \code
    namespace vigra {
        template <int ORDER, class T,
                class DestIterator, class DestAccessor,
                class C>
        void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                                 DestIterator dul, DestIterator dlr, DestAccessor dest,
                                 MultiArrayView<2, double, C> const & projectiveMatrix);
    }
    \endcode

    use argument objects in conjunction with \ref ArgumentObjectFactories :
    \code
    namespace vigra {
        template <int ORDER, class T,
                class DestIterator, class DestAccessor,
                class C>
        void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                                 triple<DestIterator, DestIterator, DestAccessor> dest,
                                 MultiArrayView<2, double, C> const & projectiveMatrix);
    }
    \endcode
    \deprecatedEnd

    The algorithm applies the given \a projectiveMatrix to the destination coordinates and copies
    the image value from the resulting source coordinates, using the given SplineImageView \a src for interpolation.
    If the resulting coordinate is outside the source image, nothing will be written at that destination point.

    \code
        for all dest pixels:
            currentSrcCoordinate = projectiveMatrix * currentDestCoordinate;
            if src.isInside(currentSrcCoordinate):
                dest[currentDestCoordinate] = src[currentSrcCoordinate]; // copy an interpolated value
    \endcode

    The matrix represent a 2-dimensional projective transform by means of homogeneous coordinates,
    i.e. it must be a 3x3 matrix whose last row is (p1,p2,1).

     Required Interface:

    \code
    DestImageIterator dest_upperleft;

    double x = ..., y = ...;

    if (spline.isInside(x,y))
        dest_accessor.set(spline(x, y), dest_upperleft);

    \endcode

    See also: Functions to specify projective transformation: \ref translationMatrix2D(), \ref scalingMatrix2D(),
                    \ref shearMatrix2D(), \ref rotationMatrix2DRadians(), \ref rotationMatrix2DDegrees() and \ref projectiveMatrix2DFromCorrespondingPoints()
*/
doxygen_overloaded_function(template <...> void projectiveWarpImage)

template <int ORDER, class T,
          class DestIterator, class DestAccessor,
          class C>
void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                     DestIterator dul, DestIterator dlr, DestAccessor dest,
                     MultiArrayView<2, double, C> const & projectiveMatrix)
{
    vigra_precondition(rowCount(projectiveMatrix) == 3 && columnCount(projectiveMatrix) == 3 && projectiveMatrix(2,2) == 1.0,
        "projectiveWarpImage(): matrix doesn't represent an projective transformation with homogeneous 2D coordinates.");

    double w = dlr.x - dul.x;
    double h = dlr.y - dul.y;

    for(double y = 0.0; y < h; ++y, ++dul.y)
    {
        typename DestIterator::row_iterator rd = dul.rowIterator();
        for(double x=0.0; x < w; ++x, ++rd)
        {
            double fac = 1.0/(x*projectiveMatrix(2,0) + y*projectiveMatrix(2,1) + 1);
            double sx = (x*projectiveMatrix(0,0) + y*projectiveMatrix(0,1) + projectiveMatrix(0,2)) * fac;
            double sy = (x*projectiveMatrix(1,0) + y*projectiveMatrix(1,1) + projectiveMatrix(1,2)) * fac;
            if(src.isInside(sx, sy))
                dest.set(src(sx, sy), rd);
        }
    }
}

template <int ORDER, class T,
          class DestIterator, class DestAccessor,
          class C>
inline
void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                     triple<DestIterator, DestIterator, DestAccessor> dest,
                     MultiArrayView<2, double, C> const & projectiveMatrix)
{
    projectiveWarpImage(src, dest.first, dest.second, dest.third, projectiveMatrix);
}

template <int ORDER, class T,
          class T2, class S2,
          class C>
inline
void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                          MultiArrayView<2, T2, S2> dest,
                          MultiArrayView<2, double, C> const & projectiveMatrix)
{
    projectiveWarpImage(src, destImageRange(dest), projectiveMatrix);
}

//@}

} // namespace vigra

#endif /* VIGRA_PROJECTIVE_REGISTRATION_HXX */
<commit_msg>Move calculation out of possibly omitted assert macro<commit_after>/************************************************************************/
/*                                                                      */
/*               Copyright 2007-2014 by Benjamin Seppke                 */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_PROJECTIVE_REGISTRATION_HXX
#define VIGRA_PROJECTIVE_REGISTRATION_HXX

#include "mathutil.hxx"
#include "matrix.hxx"
#include "linear_solve.hxx"
#include "tinyvector.hxx"
#include "splineimageview.hxx"

namespace vigra
{

/** \addtogroup Registration Image Registration
 */
//@{

/********************************************************/
/*                                                      */
/*     projectiveMatrix2DFromCorrespondingPoints        */
/*                                                      */
/********************************************************/

/** \brief Create homogeneous matrix that maps corresponding points onto each other.

    For use with \ref projectiveWarpImage(). Since four corresponding points are needed to be given,
    the matrix will compute a full projective transform.
 */
template <class SrcPointIterator, class DestPointIterator>
linalg::TemporaryMatrix<double>
projectiveMatrix2DFromCorrespondingPoints(SrcPointIterator s, SrcPointIterator send, DestPointIterator d)
{
    //Calculate the matrix using least squares of all points of points like the result is:
    // ( x2 )   ( s_x        r1        t_x )   ( x1 )
    // ( y2 ) = (  r2        s_y        t_y ) * ( y1 )
    // (  1 )   (  p1        p2        1   )   (  1 )
    int size = send - s;

    vigra_assert(size >= 4,
                 "projectiveMatrix2DFromCorrespondingPoints(): need at least four corresponding points.");

    vigra::Matrix<double> A(2*size,8, 0.0), b(2*size,1),  res(8,1);
    for (int i =0; i<size; ++i, ++s, ++d)
    {
        //m_00                m_01                m_02                m_10                    m_11                    m_12                m_20                                m_21
        //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        A(i,0)=(*d)[0];        A(i,1)=(*d)[1];        A(i,2)=1;            A(i,3)=0;                A(i,4)=0;                A(i,5)=0;            A(i,6)=-1*((*d)[0])*((*s)[0]);            A(i,7)=-1*((*d)[1])*((*s)[0]);
        b(i,0)=(*s)[0];

        A(size+i,0)=0;        A(size+i,1)=0;        A(size+i,2)=0;        A(size+i,3)=(*d)[0];    A(size+i,4)=(*d)[1];    A(size+i,5)=1;        A(size+i,6)=-1*((*d)[0])*((*s)[1]);        A(size+i,7)=-1*((*d)[1])*((*s)[1]);
        b(size+i,0)=(*s)[1];

    }

    bool solvable = linearSolve(A, b, res);
    // silence unused variable warning in release mode
    static_cast<void>(solvable);
    vigra_assert(solvable,
                "projectiveMatrix2DFromCorrespondingPoints(): singular solution matrix.");

    linalg::TemporaryMatrix<double> projectiveMat(3,3);
    projectiveMat(0,0) = res(0,0);        projectiveMat(0,1) = res(1,0);        projectiveMat(0,2) = res(2,0);
    projectiveMat(1,0) = res(3,0);        projectiveMat(1,1) = res(4,0);        projectiveMat(1,2) = res(5,0);
    projectiveMat(2,0) = res(6,0);        projectiveMat(2,1) = res(7,0);        projectiveMat(2,2) = 1;

    return projectiveMat;
}

/********************************************************/
/*                                                      */
/*                projectiveWarpImage                   */
/*                                                      */
/********************************************************/

/** \brief Warp an image according to an projective transformation.

    The matrix can be computed from a set of correspondung points
    using \ref projectiveMatrix2DFromCorrespondingPoints().

     Declarations:

    \#include \<vigra/projective_registration.hxx\>

    Namespace: vigra

    pass 2D array views:
    \code
    namespace vigra {
        template <int ORDER, class T,
                  class T2, class S2,
                  class C>
        void
        projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                            MultiArrayView<2, T2, S2> dest,
                            MultiArrayView<2, double, C> const & projectiveMatrix);
    }
    \endcode

    \deprecatedAPI{projectiveWarpImage}
    pass \ref ImageIterators and \ref DataAccessors :

    pass arguments explicitly:
    \code
    namespace vigra {
        template <int ORDER, class T,
                class DestIterator, class DestAccessor,
                class C>
        void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                                 DestIterator dul, DestIterator dlr, DestAccessor dest,
                                 MultiArrayView<2, double, C> const & projectiveMatrix);
    }
    \endcode

    use argument objects in conjunction with \ref ArgumentObjectFactories :
    \code
    namespace vigra {
        template <int ORDER, class T,
                class DestIterator, class DestAccessor,
                class C>
        void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                                 triple<DestIterator, DestIterator, DestAccessor> dest,
                                 MultiArrayView<2, double, C> const & projectiveMatrix);
    }
    \endcode
    \deprecatedEnd

    The algorithm applies the given \a projectiveMatrix to the destination coordinates and copies
    the image value from the resulting source coordinates, using the given SplineImageView \a src for interpolation.
    If the resulting coordinate is outside the source image, nothing will be written at that destination point.

    \code
        for all dest pixels:
            currentSrcCoordinate = projectiveMatrix * currentDestCoordinate;
            if src.isInside(currentSrcCoordinate):
                dest[currentDestCoordinate] = src[currentSrcCoordinate]; // copy an interpolated value
    \endcode

    The matrix represent a 2-dimensional projective transform by means of homogeneous coordinates,
    i.e. it must be a 3x3 matrix whose last row is (p1,p2,1).

     Required Interface:

    \code
    DestImageIterator dest_upperleft;

    double x = ..., y = ...;

    if (spline.isInside(x,y))
        dest_accessor.set(spline(x, y), dest_upperleft);

    \endcode

    See also: Functions to specify projective transformation: \ref translationMatrix2D(), \ref scalingMatrix2D(),
                    \ref shearMatrix2D(), \ref rotationMatrix2DRadians(), \ref rotationMatrix2DDegrees() and \ref projectiveMatrix2DFromCorrespondingPoints()
*/
doxygen_overloaded_function(template <...> void projectiveWarpImage)

template <int ORDER, class T,
          class DestIterator, class DestAccessor,
          class C>
void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                     DestIterator dul, DestIterator dlr, DestAccessor dest,
                     MultiArrayView<2, double, C> const & projectiveMatrix)
{
    vigra_precondition(rowCount(projectiveMatrix) == 3 && columnCount(projectiveMatrix) == 3 && projectiveMatrix(2,2) == 1.0,
        "projectiveWarpImage(): matrix doesn't represent an projective transformation with homogeneous 2D coordinates.");

    double w = dlr.x - dul.x;
    double h = dlr.y - dul.y;

    for(double y = 0.0; y < h; ++y, ++dul.y)
    {
        typename DestIterator::row_iterator rd = dul.rowIterator();
        for(double x=0.0; x < w; ++x, ++rd)
        {
            double fac = 1.0/(x*projectiveMatrix(2,0) + y*projectiveMatrix(2,1) + 1);
            double sx = (x*projectiveMatrix(0,0) + y*projectiveMatrix(0,1) + projectiveMatrix(0,2)) * fac;
            double sy = (x*projectiveMatrix(1,0) + y*projectiveMatrix(1,1) + projectiveMatrix(1,2)) * fac;
            if(src.isInside(sx, sy))
                dest.set(src(sx, sy), rd);
        }
    }
}

template <int ORDER, class T,
          class DestIterator, class DestAccessor,
          class C>
inline
void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                     triple<DestIterator, DestIterator, DestAccessor> dest,
                     MultiArrayView<2, double, C> const & projectiveMatrix)
{
    projectiveWarpImage(src, dest.first, dest.second, dest.third, projectiveMatrix);
}

template <int ORDER, class T,
          class T2, class S2,
          class C>
inline
void projectiveWarpImage(SplineImageView<ORDER, T> const & src,
                          MultiArrayView<2, T2, S2> dest,
                          MultiArrayView<2, double, C> const & projectiveMatrix)
{
    projectiveWarpImage(src, destImageRange(dest), projectiveMatrix);
}

//@}

} // namespace vigra

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


<commit_before>/**
 * @file		exception.hpp
 * @brief		COSSB exception
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 8. 23
 * @details	cossb exception header
 */

#ifndef _COSSB_EXCEPTION_HPP_
#define _COSSB_EXCEPTION_HPP_

#include <string>
#include <iostream>
#include <exception>
#include <stdexcept>
#include "logger.hpp"

using namespace std;

namespace cossb {
namespace exception {
class cossb_exception : public std::exception {
public:
	cossb_exception(const char* msg) : exception_str(msg) { }
	~cossb_exception() throw() { }
	virtual const char* what() const throw() {
		return exception_str.c_str();
	}
protected:
	void set(const char* msg) { exception_str = msg; }
private:
	std::string exception_str;
};
} /* namespace exception */

/**
 * @brief	broker exception
 */
namespace broker {
enum class excode : int { DRIVER_NOT_FOUND=0, };

class exception : public cossb::exception::cossb_exception {
public:
	exception(broker::excode code):cossb::exception::cossb_exception("unknown exception") {
		switch(code)
		{
		case	excode::DRIVER_NOT_FOUND: set("Driver cannot be found");  break;
		}
	}
};

} /* namespace broker */

} /* namespace cossb */

#endif /* _COSSB_EXCEPTION_HPP_ */
<commit_msg>insert default case<commit_after>/**
 * @file		exception.hpp
 * @brief		COSSB exception
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 8. 23
 * @details	cossb exception header
 */

#ifndef _COSSB_EXCEPTION_HPP_
#define _COSSB_EXCEPTION_HPP_

#include <string>
#include <iostream>
#include <exception>
#include <stdexcept>
#include "logger.hpp"

using namespace std;

namespace cossb {
namespace exception {
class cossb_exception : public std::exception {
public:
	cossb_exception(const char* msg) : exception_str(msg) { }
	~cossb_exception() throw() { }
	virtual const char* what() const throw() {
		return exception_str.c_str();
	}
protected:
	void set(const char* msg) { exception_str = msg; }
private:
	std::string exception_str;
};
} /* namespace exception */

/**
 * @brief	broker exception
 */
namespace broker {
enum class excode : int { DRIVER_NOT_FOUND=0, };

class exception : public cossb::exception::cossb_exception {
public:
	exception(broker::excode code):cossb::exception::cossb_exception("") {
		switch(code)
		{
		case	excode::DRIVER_NOT_FOUND: set("Driver cannot be found");  break;
		default:
			set("Unknown Exception");
		}
	}
};

} /* namespace broker */

} /* namespace cossb */

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


<commit_before>#include "HopsanTypes.h"
#include <cstdlib>
#include <cstring>
#include <string>

using namespace hopsan;

HString::HString()
{
    mpDataBuffer=0;
    mSize=0;
}

HString::~HString()
{
    clear();
}

HString::HString(const char *str)
{
    mpDataBuffer=0;
    mSize=0;
    setString(str);
}

//! @brief Copy constructor
HString::HString(const HString &rOther)
{
    mpDataBuffer=0;
    mSize=0;
    setString(rOther.c_str());
}

HString::HString(const HString &rOther, const size_t pos, const size_t len)
{
    mpDataBuffer=0;
    mSize=0;

    // First caluclate end index and make sure it is within bounds
    size_t otherNumChar;
    if (len == npos)
    {
        otherNumChar = rOther.size()-pos;
    }
    else
    {
        // If given length is within bounds, use it
        if (pos+len <= rOther.size())
        {
            otherNumChar = pos+len;
        }
        // Else use the maximum allowed length
        else
        {
            otherNumChar = rOther.size()-pos;
        }
    }

    // Reallocate memmory and copy string
    mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,otherNumChar+1));
    mSize = otherNumChar;
    strncpy(mpDataBuffer, rOther.c_str()+pos, otherNumChar);
    mpDataBuffer[mSize] = '\0';
}

//! @brief Set the string by copying const char*
//! @param [in] str The string data to copy
void HString::setString(const char *str)
{
    const size_t s = strlen(str);
    if (s>0)
    {
        mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,s+1));
        strcpy(mpDataBuffer, str);
        mSize = s;
    }
    else
    {
        clear();
    }
}

HString &HString::append(const char *str)
{
    size_t s = strlen(str);
    if (s>0)
    {
        s += size();
        mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,s+1));
        strcpy(mpDataBuffer+size(), str);
        mSize = s;
    }
    return *this;
}

HString &HString::append(const char chr)
{
    mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,size()+2));
    mpDataBuffer[mSize] = chr;
    mSize = mSize+1;
    mpDataBuffer[mSize] = '\0';

    return *this;
}

HString &HString::append(const HString &str)
{
    this->append(str.c_str());
    return *this;
}

HString &HString::erase(size_t pos, size_t len)
{
    HString n1(*this, 0, pos);
    HString n2(*this, pos+len);
    setString((n1+n2).c_str());
    return *this;
}

//! @brief Returns a c_str pointer to internal data
//! @note The pointer is only valid, while the HString object is alive
const char *HString::c_str() const
{
    if (mpDataBuffer)
    {
        return mpDataBuffer;
    }
    else
    {
        //! @todo will this work when mpDataBuffer == 0
        return "";
    }

}

size_t HString::size() const
{
    return mSize;
}

//! @brief Check if string is empty
//! @returns True if empty, else False
bool HString::empty() const
{
    return (mSize==0);
}

//! @brief Compare string to const char*
//! @param [in] other The string to compare to
//! @returns True if same, else False
bool HString::compare(const char *other) const
{
    if (strlen(other) != size())
    {
        return false;
    }
    else
    {
        return (strcmp(mpDataBuffer,other) == 0);
    }
}

bool HString::compare(const HString &rOther) const
{
    if (mSize != rOther.size())
    {
        return false;
    }
    return (strcmp(mpDataBuffer, rOther.c_str()) == 0);
}

size_t HString::find_first_of(const char c, size_t pos) const
{
    return find(c,pos);
}

size_t HString::rfind(const char c, size_t pos) const
{
    size_t i = pos;
    if (i > mSize)
    {
        i = mSize;
    }
    for ( ; i>0; --i)
    {
        if (mpDataBuffer[i-1] == c)
        {
            return i-1;
        }
    }
    return npos;
}

size_t HString::find(const char c, size_t pos) const
{
    for (size_t i=pos; i<mSize; ++i)
    {
        if (mpDataBuffer[i] == c)
        {
            return i;
        }
    }
    return npos;
}

size_t HString::find(const char *s, size_t pos) const
{
    const char* pFirst = strstr(mpDataBuffer+pos, s);
    if (pFirst)
    {
        return (pFirst - mpDataBuffer);
    }
    else
    {
        return npos;
    }
}

size_t HString::find(const HString &s, size_t pos) const
{
    return find(s.c_str(),pos);
}

bool HString::containes(const HString &rString) const
{
    return (find(rString) != npos);
}

bool HString::containes(const char c) const
{
    return (find(c) != npos);
}

bool HString::containes(const char *s) const
{
    return (find(s) != npos);
}

char HString::front() const
{
    return mpDataBuffer[0];
}

char &HString::front()
{
    return mpDataBuffer[0];
}

char HString::back() const
{
    return mpDataBuffer[mSize-1];
}

char &HString::back()
{
    return mpDataBuffer[mSize-1];
}

char HString::at(const size_t pos) const
{
    if (pos < mSize)
    {
        return mpDataBuffer[pos];
    }
    else
    {
        return '\0';
    }
}

bool HString::operator <(const HString &rhs) const
{
    if (empty())
    {
        return strcmp("", rhs.c_str()) < 0;
    }
    else
    {
        return strcmp(mpDataBuffer, rhs.c_str()) < 0;
    }
}

//! @todo these could be inlined
HString &HString::operator +=(const HString &rhs)
{
    return append(rhs.c_str());
}

HString &HString::operator +=(const char *rhs)
{
    return append(rhs);
}

HString &HString::operator +=(const char rhs)
{
    return append(rhs);
}

char &HString::operator [](const size_t idx)
{
    return mpDataBuffer[idx];
}

const char &HString::operator [](const size_t idx) const
{
    return mpDataBuffer[idx];
}

HString &HString::operator =(const char *rhs)
{
    setString(rhs);
    return *this;
}

HString &HString::operator =(const char rhs)
{
    setString(" ");
    mpDataBuffer[0]=rhs;
    return *this;
}

HString& HString::operator=(const HString &rhs)
{
    setString(rhs.c_str());
    return *this;
}

//! @brief Clear the string
void HString::clear()
{
    if (mpDataBuffer)
    {
        free(mpDataBuffer);
        mSize = 0;
        mpDataBuffer=0;
    }
}

void HString::replace(const size_t pos, const size_t len, const char *str)
{
    //! @todo do this properly without using local string
    std::string temp = mpDataBuffer;
    temp.replace(pos, len, str);
    this->setString(temp.c_str());
}

HString &HString::replace(const char *oldstr, const char *newstr)
{
    size_t pos = find(oldstr);
    while (pos!=HString::npos)
    {
        replace(pos, strlen(oldstr), newstr);
        pos = find(oldstr);
    }
    return *this;
}

HString &HString::replace(const HString &rOldstr, const HString &rNewstr)
{
    return replace(rOldstr.c_str(), rNewstr.c_str());
}

//! @brief Extract substring
//! @param [in] pos First index of substring
//! @param [in] len Num bytes in substring, or HString::npos for all
//! @returns A substring
HString HString::substr(const size_t pos, const size_t len) const
{
    HString sub(*this, pos, len);
    return sub;
}
<commit_msg>Fixed bug in HString compare<commit_after>#include "HopsanTypes.h"
#include <cstdlib>
#include <cstring>
#include <string>

using namespace hopsan;

HString::HString()
{
    mpDataBuffer=0;
    mSize=0;
}

HString::~HString()
{
    clear();
}

HString::HString(const char *str)
{
    mpDataBuffer=0;
    mSize=0;
    setString(str);
}

//! @brief Copy constructor
HString::HString(const HString &rOther)
{
    mpDataBuffer=0;
    mSize=0;
    setString(rOther.c_str());
}

HString::HString(const HString &rOther, const size_t pos, const size_t len)
{
    mpDataBuffer=0;
    mSize=0;

    // First caluclate end index and make sure it is within bounds
    size_t otherNumChar;
    if (len == npos)
    {
        otherNumChar = rOther.size()-pos;
    }
    else
    {
        // If given length is within bounds, use it
        if (pos+len <= rOther.size())
        {
            otherNumChar = pos+len;
        }
        // Else use the maximum allowed length
        else
        {
            otherNumChar = rOther.size()-pos;
        }
    }

    // Reallocate memmory and copy string
    mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,otherNumChar+1));
    mSize = otherNumChar;
    strncpy(mpDataBuffer, rOther.c_str()+pos, otherNumChar);
    mpDataBuffer[mSize] = '\0';
}

//! @brief Set the string by copying const char*
//! @param [in] str The string data to copy
void HString::setString(const char *str)
{
    const size_t s = strlen(str);
    if (s>0)
    {
        mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,s+1));
        strcpy(mpDataBuffer, str);
        mSize = s;
    }
    else
    {
        clear();
    }
}

HString &HString::append(const char *str)
{
    size_t s = strlen(str);
    if (s>0)
    {
        s += size();
        mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,s+1));
        strcpy(mpDataBuffer+size(), str);
        mSize = s;
    }
    return *this;
}

HString &HString::append(const char chr)
{
    mpDataBuffer = static_cast<char*>(realloc(mpDataBuffer,size()+2));
    mpDataBuffer[mSize] = chr;
    mSize = mSize+1;
    mpDataBuffer[mSize] = '\0';

    return *this;
}

HString &HString::append(const HString &str)
{
    this->append(str.c_str());
    return *this;
}

HString &HString::erase(size_t pos, size_t len)
{
    HString n1(*this, 0, pos);
    HString n2(*this, pos+len);
    setString((n1+n2).c_str());
    return *this;
}

//! @brief Returns a c_str pointer to internal data
//! @note The pointer is only valid, while the HString object is alive
const char *HString::c_str() const
{
    if (mpDataBuffer)
    {
        return mpDataBuffer;
    }
    else
    {
        //! @todo will this work when mpDataBuffer == 0
        return "";
    }

}

size_t HString::size() const
{
    return mSize;
}

//! @brief Check if string is empty
//! @returns True if empty, else False
bool HString::empty() const
{
    return (mSize==0);
}

//! @brief Compare string to const char*
//! @param [in] other The string to compare to
//! @returns True if same, else False
bool HString::compare(const char *other) const
{
    if (strlen(other) != size())
    {
        return false;
    }
    else
    {
        return (strcmp(mpDataBuffer,other) == 0);
    }
}

bool HString::compare(const HString &rOther) const
{
    if (mSize != rOther.size())
    {
        return false;
    }
    else if ( (mSize == rOther.size()) && (mSize == 0) )
    {
        return true;
    }
    else
    {
        return (strcmp(mpDataBuffer, rOther.c_str()) == 0);
    }
}

size_t HString::find_first_of(const char c, size_t pos) const
{
    return find(c,pos);
}

size_t HString::rfind(const char c, size_t pos) const
{
    size_t i = pos;
    if (i > mSize)
    {
        i = mSize;
    }
    for ( ; i>0; --i)
    {
        if (mpDataBuffer[i-1] == c)
        {
            return i-1;
        }
    }
    return npos;
}

size_t HString::find(const char c, size_t pos) const
{
    for (size_t i=pos; i<mSize; ++i)
    {
        if (mpDataBuffer[i] == c)
        {
            return i;
        }
    }
    return npos;
}

size_t HString::find(const char *s, size_t pos) const
{
    const char* pFirst = strstr(mpDataBuffer+pos, s);
    if (pFirst)
    {
        return (pFirst - mpDataBuffer);
    }
    else
    {
        return npos;
    }
}

size_t HString::find(const HString &s, size_t pos) const
{
    return find(s.c_str(),pos);
}

bool HString::containes(const HString &rString) const
{
    return (find(rString) != npos);
}

bool HString::containes(const char c) const
{
    return (find(c) != npos);
}

bool HString::containes(const char *s) const
{
    return (find(s) != npos);
}

char HString::front() const
{
    return mpDataBuffer[0];
}

char &HString::front()
{
    return mpDataBuffer[0];
}

char HString::back() const
{
    return mpDataBuffer[mSize-1];
}

char &HString::back()
{
    return mpDataBuffer[mSize-1];
}

char HString::at(const size_t pos) const
{
    if (pos < mSize)
    {
        return mpDataBuffer[pos];
    }
    else
    {
        return '\0';
    }
}

bool HString::operator <(const HString &rhs) const
{
    if (empty())
    {
        return strcmp("", rhs.c_str()) < 0;
    }
    else
    {
        return strcmp(mpDataBuffer, rhs.c_str()) < 0;
    }
}

//! @todo these could be inlined
HString &HString::operator +=(const HString &rhs)
{
    return append(rhs.c_str());
}

HString &HString::operator +=(const char *rhs)
{
    return append(rhs);
}

HString &HString::operator +=(const char rhs)
{
    return append(rhs);
}

char &HString::operator [](const size_t idx)
{
    return mpDataBuffer[idx];
}

const char &HString::operator [](const size_t idx) const
{
    return mpDataBuffer[idx];
}

HString &HString::operator =(const char *rhs)
{
    setString(rhs);
    return *this;
}

HString &HString::operator =(const char rhs)
{
    setString(" ");
    mpDataBuffer[0]=rhs;
    return *this;
}

HString& HString::operator=(const HString &rhs)
{
    setString(rhs.c_str());
    return *this;
}

//! @brief Clear the string
void HString::clear()
{
    if (mpDataBuffer)
    {
        free(mpDataBuffer);
        mSize = 0;
        mpDataBuffer=0;
    }
}

void HString::replace(const size_t pos, const size_t len, const char *str)
{
    //! @todo do this properly without using local string
    std::string temp = mpDataBuffer;
    temp.replace(pos, len, str);
    this->setString(temp.c_str());
}

HString &HString::replace(const char *oldstr, const char *newstr)
{
    size_t pos = find(oldstr);
    while (pos!=HString::npos)
    {
        replace(pos, strlen(oldstr), newstr);
        pos = find(oldstr);
    }
    return *this;
}

HString &HString::replace(const HString &rOldstr, const HString &rNewstr)
{
    return replace(rOldstr.c_str(), rNewstr.c_str());
}

//! @brief Extract substring
//! @param [in] pos First index of substring
//! @param [in] len Num bytes in substring, or HString::npos for all
//! @returns A substring
HString HString::substr(const size_t pos, const size_t len) const
{
    HString sub(*this, pos, len);
    return sub;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DBN_FAST_EXPR_HPP
#define DBN_FAST_EXPR_HPP

#include "fast_op.hpp"
#include "utils.hpp"

template <typename T, typename LeftExpr, typename BinaryOp, typename RightExpr>
class fast_expr {
private:
    LeftExpr _lhs;
    RightExpr _rhs;

    typedef fast_expr<T, LeftExpr, BinaryOp, RightExpr> this_type;

public:
    //Cannot be constructed with no args
    fast_expr() = delete;

    //Construct a new expression
    fast_expr(LeftExpr l, RightExpr r) :
            _lhs(std::forward<LeftExpr>(l)), _rhs(std::forward<RightExpr>(r)){
        //Nothing else to init
    }

    //No copying
    fast_expr(const fast_expr&) = delete;
    fast_expr& operator=(const fast_expr&) = delete;

    //Make sure move is supported
    fast_expr(fast_expr&&) = default;
    fast_expr& operator=(fast_expr&&) = default;

    //Accessors

    typename std::add_lvalue_reference<LeftExpr>::type lhs(){
        return _lhs;
    }

    typename std::add_lvalue_reference<typename std::add_const<LeftExpr>::type>::type lhs() const {
        return _lhs;
    }

    typename std::add_lvalue_reference<RightExpr>::type rhs(){
        return _rhs;
    }

    typename std::add_lvalue_reference<typename std::add_const<RightExpr>::type>::type rhs() const {
        return _rhs;
    }

    //Create more complex expressions

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator+(RE re) const -> fast_expr<T, this_type const&, plus_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator+(RE&& re) const -> fast_expr<T, this_type const&, plus_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator-(RE re) const -> fast_expr<T, this_type const&, minus_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator-(RE&& re) const -> fast_expr<T, this_type const&, minus_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator*(RE re) const -> fast_expr<T, this_type const&, mul_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator*(RE&& re) const -> fast_expr<T, this_type const&, mul_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator/(RE re) const -> fast_expr<T, this_type const&, div_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator/(RE&& re) const -> fast_expr<T, this_type const&, div_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    //Apply the expression

    auto operator[](std::size_t i) const -> decltype(BinaryOp::apply(this->lhs()[i], this->rhs()[i])) {
        return BinaryOp::apply(lhs()[i], rhs()[i]);
    }
};

#endif
<commit_msg>C++14 cleanup<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DBN_FAST_EXPR_HPP
#define DBN_FAST_EXPR_HPP

#include "fast_op.hpp"
#include "utils.hpp"

template <typename T, typename LeftExpr, typename BinaryOp, typename RightExpr>
class fast_expr {
private:
    LeftExpr _lhs;
    RightExpr _rhs;

    typedef fast_expr<T, LeftExpr, BinaryOp, RightExpr> this_type;

public:
    //Cannot be constructed with no args
    fast_expr() = delete;

    //Construct a new expression
    fast_expr(LeftExpr l, RightExpr r) :
            _lhs(std::forward<LeftExpr>(l)), _rhs(std::forward<RightExpr>(r)){
        //Nothing else to init
    }

    //No copying
    fast_expr(const fast_expr&) = delete;
    fast_expr& operator=(const fast_expr&) = delete;

    //Make sure move is supported
    fast_expr(fast_expr&&) = default;
    fast_expr& operator=(fast_expr&&) = default;

    //Accessors

    typename std::add_lvalue_reference<LeftExpr>::type lhs(){
        return _lhs;
    }

    typename std::add_lvalue_reference<typename std::add_const<LeftExpr>::type>::type lhs() const {
        return _lhs;
    }

    typename std::add_lvalue_reference<RightExpr>::type rhs(){
        return _rhs;
    }

    typename std::add_lvalue_reference<typename std::add_const<RightExpr>::type>::type rhs() const {
        return _rhs;
    }

    //Create more complex expressions

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator+(RE re) const -> fast_expr<T, this_type const&, plus_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator+(RE&& re) const -> fast_expr<T, this_type const&, plus_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator-(RE re) const -> fast_expr<T, this_type const&, minus_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator-(RE&& re) const -> fast_expr<T, this_type const&, minus_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator*(RE re) const -> fast_expr<T, this_type const&, mul_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator*(RE&& re) const -> fast_expr<T, this_type const&, mul_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    template<typename RE, typename = std::enable_if_t<std::is_convertible<RE, T>::value>>
    auto operator/(RE re) const -> fast_expr<T, this_type const&, div_binary_op<T>, scalar<T>> {
        return {*this, re};
    }

    template<typename RE, typename = disable_if_t<std::is_convertible<RE, T>::value>>
    auto operator/(RE&& re) const -> fast_expr<T, this_type const&, div_binary_op<T>, decltype(std::forward<RE>(re))>{
        return {*this, std::forward<RE>(re)};
    }

    //Apply the expression

    decltype(auto) operator[](std::size_t i) const {
        return BinaryOp::apply(lhs()[i], rhs()[i]);
    }
};

#endif
<|endoftext|>


<commit_before>#ifndef FMO_IMAGE_HPP
#define FMO_IMAGE_HPP

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace cv {
    class Mat;
}

namespace fmo {
    /// An object that wraps the OpenCV Mat class.
    struct Mat {
        /// Wraps the data pointer in a Mat object.
        virtual cv::Mat wrap() = 0;

        /// Wraps the data pointer in a Mat object. Be careful with this one -- use the returned Mat
        /// only for reading.
        virtual cv::Mat wrap() const = 0;
    };

    /// An image buffer class. Wraps the OpenCV Mat class. Has value semantics, i.e. copying an
    /// instance of Image will perform a copy of the entire image data.
    struct Image : public Mat {
        /// Possible internal color formats.
        enum class Format : char {
            UNKNOWN = 0,
            GRAY,
            BGR,
            YUV420SP,
        };

        /// Image dimensions.
        struct Dims {
            int width, height;

            friend bool operator==(const Dims& lhs, const Dims& rhs) {
                return lhs.width == rhs.width && lhs.height == rhs.height;
            }

            friend bool operator!=(const Dims& lhs, const Dims& rhs) { return !(lhs == rhs); }
        };

        using iterator = uint8_t*;
        using const_iterator = const uint8_t*;

        ~Image() = default;
        Image() = default;

        /// Copies the contents from another image.
        Image(const Image& rhs) { assign(rhs.mFormat, rhs.mDims, rhs.mData.data()); }

        /// Copies the contents from another image.
        Image& operator=(const Image& rhs) {
            assign(rhs.mFormat, rhs.mDims, rhs.mData.data());
            return *this;
        }

        /// Swaps the contents of the image with another image.
        Image(Image&& rhs) noexcept { swap(rhs); }

        /// Swaps the contents of the image with another image.
        Image& operator=(Image&& rhs) noexcept {
            swap(rhs);
            return *this;
        }

        /// Reads an image from file and converts it to the desired format.
        Image(const std::string& filename, Format format);

        /// Copies an image from memory.
        Image(Format format, Dims dims, const uint8_t* data) { assign(format, dims, data); }

        /// Copies an image from memory.
        void assign(Format format, Dims dims, const uint8_t* data);

        /// Provides current image dimensions.
        Dims dims() const { return mDims; }

        /// Provides current image format.
        Format format() const { return mFormat; }

        /// The number of bytes in the image.
        size_t size() const { return mData.size(); }

        /// Provides direct access to the underlying data.
        uint8_t* data() { return mData.data(); }

        /// Provides direct access to the underlying data.
        const uint8_t* data() const { return mData.data(); }

        /// Provides iterator access to the underlying data.
        iterator begin() { return mData.data(); }

        /// Provides iterator access to the underlying data.
        const_iterator begin() const { return mData.data(); }

        /// Provides iterator access to the underlying data.
        friend iterator begin(Image& img) { return img.mData.data(); }

        /// Provides iterator access to the underlying data.
        friend const_iterator begin(const Image& img) { return img.mData.data(); }

        /// Provides iterator access to the underlying data.
        iterator end() { return begin() + mData.size(); }

        /// Provides iterator access to the underlying data.
        const_iterator end() const { return begin() + mData.size(); }

        /// Provides iterator access to the underlying data.
        friend iterator end(Image& img) { return img.end(); }

        /// Provides iterator access to the underlying data.
        friend const_iterator end(const Image& img) { return img.end(); }

        /// Converts the image "src" to a given color format and saves the result to "dest". One
        /// couild pass the same object as both "src" and "dest", but doing so is ineffective,
        /// unless the conversion is YUV420SP to GRAY. Only some conversions are supported, namely:
        /// GRAY to BGR, BGR to GRAY, YUV420SP to BGR, YUV420SP to GRAY.
        static void convert(const Image& src, Image& dest, Format format);

        /// Swaps the contents of the two Image instances.
        void swap(Image& rhs) noexcept {
            mData.swap(rhs.mData);
            std::swap(mDims, rhs.mDims);
            std::swap(mFormat, rhs.mFormat);
        }

        /// Removes all data and sets the size to zero. Does not deallocate any memory.
        void clear() noexcept {
            mData.clear();
            mDims = {0, 0};
            mFormat = Format::UNKNOWN;
        }

        /// Swaps the contents of the two Image instances.
        friend void swap(Image& lhs, Image& rhs) noexcept { lhs.swap(rhs); }

    private:
        /// Resizes the image to math the desired format and dimensions. When the size increases,
        /// iterators may get invalidated and all previous contents may be erased.
        void resize(Format format, Dims dims);

        /// Wraps the data pointer in a Mat object.
        virtual cv::Mat wrap() override final;

        /// Wraps the data pointer in a Mat object. Be careful with this one -- use the returned Mat
        /// only for reading.
        virtual cv::Mat wrap() const override final;

        // data
        std::vector<uint8_t> mData;
        Dims mDims = {0, 0};
        Format mFormat = Format::UNKNOWN;
    };
}

#endif // FMO_IMAGE_HPP
<commit_msg>Make resize() and wrap() public<commit_after>#ifndef FMO_IMAGE_HPP
#define FMO_IMAGE_HPP

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace cv {
    class Mat;
}

namespace fmo {
    /// An object that wraps the OpenCV Mat class.
    struct Mat {
        /// Wraps the data pointer in a Mat object.
        virtual cv::Mat wrap() = 0;

        /// Wraps the data pointer in a Mat object. Be careful with this one -- use the returned Mat
        /// only for reading.
        virtual cv::Mat wrap() const = 0;
    };

    /// An image buffer class. Wraps the OpenCV Mat class. Has value semantics, i.e. copying an
    /// instance of Image will perform a copy of the entire image data.
    struct Image : public Mat {
        /// Possible internal color formats.
        enum class Format : char {
            UNKNOWN = 0,
            GRAY,
            BGR,
            YUV420SP,
        };

        /// Image dimensions.
        struct Dims {
            int width, height;

            friend bool operator==(const Dims& lhs, const Dims& rhs) {
                return lhs.width == rhs.width && lhs.height == rhs.height;
            }

            friend bool operator!=(const Dims& lhs, const Dims& rhs) { return !(lhs == rhs); }
        };

        using iterator = uint8_t*;
        using const_iterator = const uint8_t*;

        ~Image() = default;
        Image() = default;

        /// Copies the contents from another image.
        Image(const Image& rhs) { assign(rhs.mFormat, rhs.mDims, rhs.mData.data()); }

        /// Copies the contents from another image.
        Image& operator=(const Image& rhs) {
            assign(rhs.mFormat, rhs.mDims, rhs.mData.data());
            return *this;
        }

        /// Swaps the contents of the image with another image.
        Image(Image&& rhs) noexcept { swap(rhs); }

        /// Swaps the contents of the image with another image.
        Image& operator=(Image&& rhs) noexcept {
            swap(rhs);
            return *this;
        }

        /// Reads an image from file and converts it to the desired format.
        Image(const std::string& filename, Format format);

        /// Copies an image from memory.
        Image(Format format, Dims dims, const uint8_t* data) { assign(format, dims, data); }

        /// Copies an image from memory.
        void assign(Format format, Dims dims, const uint8_t* data);

        /// Resizes the image to math the desired format and dimensions. When the size increases,
        /// iterators may get invalidated and all previous contents may be erased.
        void resize(Format format, Dims dims);

        /// Provides current image dimensions.
        Dims dims() const { return mDims; }

        /// Provides current image format.
        Format format() const { return mFormat; }

        /// The number of bytes in the image.
        size_t size() const { return mData.size(); }

        /// Provides direct access to the underlying data.
        uint8_t* data() { return mData.data(); }

        /// Provides direct access to the underlying data.
        const uint8_t* data() const { return mData.data(); }

        /// Provides iterator access to the underlying data.
        iterator begin() { return mData.data(); }

        /// Provides iterator access to the underlying data.
        const_iterator begin() const { return mData.data(); }

        /// Provides iterator access to the underlying data.
        friend iterator begin(Image& img) { return img.mData.data(); }

        /// Provides iterator access to the underlying data.
        friend const_iterator begin(const Image& img) { return img.mData.data(); }

        /// Provides iterator access to the underlying data.
        iterator end() { return begin() + mData.size(); }

        /// Provides iterator access to the underlying data.
        const_iterator end() const { return begin() + mData.size(); }

        /// Provides iterator access to the underlying data.
        friend iterator end(Image& img) { return img.end(); }

        /// Provides iterator access to the underlying data.
        friend const_iterator end(const Image& img) { return img.end(); }

        /// Converts the image "src" to a given color format and saves the result to "dest". One
        /// couild pass the same object as both "src" and "dest", but doing so is ineffective,
        /// unless the conversion is YUV420SP to GRAY. Only some conversions are supported, namely:
        /// GRAY to BGR, BGR to GRAY, YUV420SP to BGR, YUV420SP to GRAY.
        static void convert(const Image& src, Image& dest, Format format);

        /// Swaps the contents of the two Image instances.
        void swap(Image& rhs) noexcept {
            mData.swap(rhs.mData);
            std::swap(mDims, rhs.mDims);
            std::swap(mFormat, rhs.mFormat);
        }

        /// Removes all data and sets the size to zero. Does not deallocate any memory.
        void clear() noexcept {
            mData.clear();
            mDims = {0, 0};
            mFormat = Format::UNKNOWN;
        }

        /// Swaps the contents of the two Image instances.
        friend void swap(Image& lhs, Image& rhs) noexcept { lhs.swap(rhs); }

        /// Wraps the data pointer in a Mat object.
        virtual cv::Mat wrap() override final;

        /// Wraps the data pointer in a Mat object. Be careful with this one -- use the returned Mat
        /// only for reading.
        virtual cv::Mat wrap() const override final;

    private:
        std::vector<uint8_t> mData;
        Dims mDims = {0, 0};
        Format mFormat = Format::UNKNOWN;
    };
}

#endif // FMO_IMAGE_HPP
<|endoftext|>


<commit_before>#include <random>

#ifndef MAXIS_RNG_HPP
#define MAXIS_RNG_HPP

// Mixin for seeding and generating random doubles between 0 and 1
class RNG {
public:
    RNG() : engine{0}, probability{0, 1} {};

    template<typename SeedType>
    void seed_random(SeedType seed) { engine.seed(seed); };

    inline double random_prob() { return probability(engine); };
    inline size_t random_index(size_t start, size_t end) {
        std::uniform_int_distribution<size_t> range{start, end};
        return range(engine);
    };

private:
    std::mt19937 engine;
    std::uniform_real_distribution<double> probability;
};

#endif
<commit_msg>Remove inlining of RNG methods<commit_after>#include <random>

#ifndef MAXIS_RNG_H
#define MAXIS_RNG_H

// Mixin for seeding and generating random doubles between 0 and 1 and
// random indexes from start to end inclusive
class RNG {
public:
    RNG() : engine{0}, probability{0, 1} {};

    template<typename SeedType>
    void seed_random(SeedType seed) { engine.seed(seed); };

    double random_prob() { return probability(engine); };
    size_t random_index(size_t start, size_t end) {
        std::uniform_int_distribution<size_t> range{start, end};
        return range(engine);
    };

private:
    std::mt19937 engine;
    std::uniform_real_distribution<double> probability;
};

#endif
<|endoftext|>